这一章的复习主要涵盖 数组的基本性质,数组和泛型,java.util.Arrays 工具类。这里整理的都是个人觉得比较重要重新认真分析的东西,不一定全部为基础,如果有不准确的地方,还望大佬从评论区指出,感激不尽。
文章中的所有的自定义的测试都在自己的 java-review 仓库中,本文对应的链接:
dd
数组
性质
java数组是边界安全的不同于
c++,当数组的下标越出边界的时候会抛出一个ArrayIndexOutOfBoundsException数组越界的异常,后来用了c++才直到java的好,c++中越界的时候会得到一个为止的数,数组开小的时候就会出现这样的问题,不会报错可以正常编译运行还有结果,但是结果变得让人匪夷所思,根本不知道错在了哪数组为一级对象
数组的初始化中,出来第一维度以外的维度都彼此独立,相当于一个数组对象中有很多的数组引用的成员变量,引用的初始化可以延时完成。创建了的数组的数组成员都是默认的零值,这也就是为什么使用创建类的数组不会触发类的初始化的原因
数组为一级对象
前面有提到过,数组对象是虚拟机创建的,数组标识符只是一个引用
一个数组对象所持有的所有的数组元素其实就是相当于 一个对象持有的成员变量,他们初始化还非常类似
数组元素的初始化就像是创建一个对象实例的时候,类的所有的成员变量都会被初始化为他们的零值(参考 [java复习]基本类型 那篇文章中类型的零值),数组中的初始化都会被初始化为对应的零值,比如: int 会初始化为 0,
1 | // java test |
从上面的例子中,可以看出 new 一个数组对象,只需要关注最外层的数组长度就好了,因为数组的内部就相当于一个数组引用,类似于 int[] arr
以 2D 数组 为例,其另一个维度不指定的时候,就相当于了声明了一些数组引用,所以它的另一个维度不需要在声明的时候就马上确定下来,使得 另一个维度的每个数组的长度可以不一样,可以像 arr 一样,在后面进行 arr = new int[5]; 这种初始化
泛型与泛型
java中的泛型和数组不能够很好的结合
类似于泛型容器的创建方式,在前面的泛型中有介绍到
1 | // java test |
Arrays
asList()
Arrays # asList是一个泛型方法,将一个数组转化为ArrayList<E>
1 | // java 12 source |
这里得到并不是 java.util.ArrayList,而是 Arrays 的内部类,不同于 java.util.ArrayList,Arrays 的内部类只实现了 AbstractList 的一部分方法(如图所示),对于类似于 add(E e) 和 remove(E e) 方法并没有进行实现,调用这些方法的时候就会调用父类 AbstractList 中的方法抛出 UnsupportedOperationException 这个运行时异常。
1 | // java 12 source |
我们习惯上称 Arrays # asList 得到的 List 不能进行修改容量的操作,上述就是原因之一,另一个原因就是 Arrays.ArrayList 中用来保存元素的数组为 final E[] a 注定了这个数组是不能够对其容量进行修改,这两点就是 Arrays # asList 得到的容器无法进行关于容量操作的原因。
Arrays.ArrayList没有实现AbstractList中的一部分方法,如:AbstarctList # add、AbstarctList # removeArrays.ArrayList的成员变量final E[] a为不可变引用,无法改变其指向的数组Arrays.ArrayList # iterator方法得到的迭代器
copyOf()
将数组复制到一个指定长度的新数组并返回,底层通过
System # arraycopy来实现
1 | // java 12 source |
Arrays # copyOf会创建一个newLength大小的数组,并取original.length原数组长度和newLength中的较小值的那一个System # arraycopy对相同数组进行拷贝的时候前面的已经复制的值不会出现覆盖情况,同样不能越界
1 | // test |