1.Arrays.asList误区
String[] arrys = { "one", "two", "three" };
List<String> list = Arrays.asList(arrys);
list.add("four");
运行上面代码报错
原因是Arrays.asList返回的不是真正的ArrayList类,是Arrays的一个私有内部类。
而它没有重新add方法,只有调用AbstractList的add方法,直接抛出异常。
2.ArrayList fail-fast机制
解释:当某一个线程A通过iterator去遍历某集合的过程中,若该集合的内容被其他线程所改变了;那么线程A访问集合时,就会抛出ConcurrentModificationException异常。
for each遍历集合是会调用
构造Itr时会 赋值 int expectedModCount = modCount ,next时会检查 modCount != expectedModCount 如果为真就跑出抛出ConcurrentModificationException异常,发生fail-fast。
modCount是AbstractList的成员变量,记录了集合被修改的次数,我们以remove函数为例。
3.ArrayList的大小是如何自动增加的?
上面最终会调用grow方法,minCapacity的值为size+1,size为add之前集合的大小。
oldCapacity >> 1 相当于 oldCapacity /2。也就是arraylist每次扩容会扩容到 原来的size + size/2
Arrays.copyof底层就是调用 System.arraycopy方法实现数组拷贝。
4.ArrayList刚new出来,空间为0,第一次add会默认分配10个长度空间。
private static final Object[] EMPTY_ELEMENTDATA = {};
上图为add之前调的方法,判断空间为0时,就分配10个空间。
5.ArrayList真实的 数据数组为什么用transient来修饰。
我们知道 类实现了Serilizable接口,这个类的所有属性和方法都会自动序列化。ArrayList也实现了Serilizable, 但是当我们想某个属性不会被自动序列化时就使用transient来修饰。
由于elementData并不只是含有真实的元素,还有额外的没有用的空间,所以ArrayList自己重写了序列化的规则:
序列化是按真实的size来序列化的。
当对象中自定义了 writeObject 和 readObject 方法时,JVM 会调用这两个自定义方法来实现序列化与反序列化。
6.ArrayList不能装基本类型(int,long …) ,add方法会自动装箱。