数组
特点
- 数据类型一致
- 数组长度固定
- 通过索引快速查询
创建方式
- 动态创建
// 创建一个长度为5的整型数组
int[] arr = new int[5];
// 创建一个长度为3的字符串数组
String[] fruits = new String[3];
- 静态创建
// 声明并初始化一个整型数组
int[] arr1 = {1, 2, 3, 4, 5};
// 声明并初始化一个字符串数组
String[] arr2 = new String [] {"apple", "banana", "orange"};
常见异常
- 索引越界异常
int[] arr = new int[3];
System.out.println(arr[3]);
数组长度为3,索引范围是0~2,但是我们却访问了一个3的索引。
程序运行后,将会抛出ArrayIndexOutOfBoundsException 数组越界异常。
- 空指针异常
int[] arr = new int[3];
//把null赋值给数组
arr = null;
System.out.println(arr[0]);
arr = null 这行代码,意味着变量arr将不会在保存数组的内存地址,也就不允许再操作数组了,因此运行的时候会抛出 NullPointerException 空指针异常。
动态数组
动态数组比起动态数组强的地方在于可以自动地扩大容量。
特点
-
数组长度可变化
在动态数组中,数组的长度是会随着元素的增加而动态的增加,这就是动态扩容机制
1. 创建新数组,新数组的大小为原数组的1.5倍
2. 将原数组的内容复制到新数组
3. 新数组将会代替原数组成为新的内部数组 -
遍历 (迭代器)
当遍历ArrayList的过程中,同时增删ArrayList中的元素,会发生什么情况?
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(2);
list.add(3);
// 遍历ArrayList
for (Integer key : list) {
// 判断如果元素等于2,则删除
if (key.equals(2)) {
list.remove(key);
}
}
返回结果
Exception in thread "main" java.util.ConcurrentModificationException
at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1043)
at java.base/java.util.ArrayList$Itr.next(ArrayList.java:997)
at main.test1.main(test1.java:20)
报出了并发修改的错误,ConcurrentModificationException。 这是因为 forEach 使用了ArrayList内置的迭代器,这个迭代器在迭代的过程中,会校验修改次数 modCount,如果 modCount 被修改过,则抛出ConcurrentModificationException异常,快速失败(fail-fast),避免出现不可预料的结果。
// ArrayList内置的迭代器
private class Itr implements Iterator<E> {
int cursor;
int lastRet = -1;
int expectedModCount = modCount;
// 迭代下个元素
public E next() {
// 校验 modCount
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E)elementData[lastRet = i];
}
// 校验 modCount 是否被修改过
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
方法
方法(method)是将具有独立功能的代码块组织成为一个整体,使其具有特殊功能的代码集。
- 方法必须先创建才可以使用,该过程成为方法定义。
- 方法创建后并不是直接可以运行的,需要手动使用后,才执行,该过程成为方法调用。
main()方法由JVM自动调用,程序只有这一个入口。
语法格式
[修饰符列表] 返回值类型 方法名(形式参数列表){
方法体;
}
参数
形参:方法定义时的参数,由数据类型和变量名组成。
实参:方法调用时的参数,传递具体的数据。
返回值
- 不需要返回值使用void关键字定义。
public static void method1() {
System.out.print("Hello");
}
- return返回的值需要与方法定义的类型一致。
public static int method1() {
return 10;
}
方法体
方法体当中编写的是业务逻辑代码,完成某个特定功能。
// 传入数组统计高于平局分的个数
public static void getAvg(int[] arr) {
int sum = 0;
int avg = 0;
int count = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
avg = sum / arr.length;
for (int j = 0; j < arr.length; j++) {
if (arr[j] > avg) {
count++;
}
}
System.out.println("高于平均分" + avg + "的个数" + "有" + count + "个");
;
}
异常处理
try {
int[] arr1 = new int[3];
System.out.println(arr1[3]);
}catch (ArrayIndexOutOfBoundsException e){
System.out.println("索引越界异常!!!");
}
局部变量
重载
同个类中方法名相同,参数的数量、类型、顺序不同
public static double mOL(int a, double b) {
return Math.pow(a, b);
}
public static int mOL(double a,int a) {
return a * b;
}
public static String mOL(String a) {
return a;
}