public E remove(int index){ // 检查index rangeCheck(index);
modCount++; E oldValue = elementData(index);
int numMoved = size - index - 1; if (numMoved > 0) // 和 add(int index, E element)原理想通。 System.arraycopy(elementData, index+1, elementData, index, numMoved); // 引用计数为0,会自动进行垃圾回收。 elementData[--size] = null; // clear to let GC do its work // 返回旧元素 return oldValue; }
finalvoidcheckForComodification(){ if (ArrayList.this.modCount == this.expectedModCount) return; thrownew ConcurrentModificationException(); } }
一个单线程环境下的fail-fast的例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
publicstaticvoidmain(String[] args){ List<String> list = new ArrayList<>(); for (int i = 0 ; i < 10 ; i++ ) { list.add(i + ""); } Iterator<String> iterator = list.iterator(); int i = 0 ; while(iterator.hasNext()) { if (i == 3) { list.remove(3); } System.out.println(iterator.next()); i ++; } }
privatevoidwriteObject(java.io.ObjectOutputStream s) throws java.io.IOException{ // Write out element count, and any hidden stuff int expectedModCount = modCount; // 将当前类的非静态(non-static)和非瞬态(non-transient)字段写入流 // 在这里也会将size字段写入。 s.defaultWriteObject();
// Write out size as capacity for behavioural compatibility with clone() // 序列化数组包含元素数量,为了向后兼容 // 两次将size写入流 s.writeInt(size);
// Write out all elements in the proper order. // 按照顺序写入,只写入到数组包含元素的结尾,并不会把数组的所有容量区域全部写入 for (int i=0; i<size; i++) { s.writeObject(elementData[i]); } // 判断是否触发Fast-Fail if (modCount != expectedModCount) { thrownew ConcurrentModificationException(); } } privatevoidreadObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { // 设置数组引用空数组。 elementData = EMPTY_ELEMENTDATA;
// Read in size, and any hidden stuff // 将流中的的非静态(non-static)和非瞬态(non-transient)字段读取到当前类 // 包含 size s.defaultReadObject();
// Read in capacity // 读入元素个数,没什么用,只是因为写出的时候写了size属性,读的时候也要按顺序来读 s.readInt(); // ignored
if (size > 0) { // be like clone(), allocate array based upon size not capacity // 根据size计算容量。 int capacity = calculateCapacity(elementData, size); // SharedSecrets 一个“共享机密”存储库,它是一种机制, // 用于调用另一个包中的实现专用方法,而不使用反射。TODO SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, capacity); // 检查是否需要扩容 ensureCapacityInternal(size);
Object[] a = elementData; // Read in all elements in the proper order. // 依次读取元素到数组中 for (int i=0; i<size; i++) { a[i] = s.readObject(); } } }