注意: 在扩容方法中有一处很奇怪的地方,在数组中使用的最大长度为MAX_ARRAY_SIZE,它的值是Integer.MAX_VALUE - 8;
这是因为在虚拟机中,普通对象可以通过元数据确定对象的大小,而数组,直接通过元数据是无法获取数组长度的,需要有一定的空间去存储数组的长度的值。这个时候就是Integer.MAX_VALUE - 8的意义所在。
那么,可不可以使用Integer.MAX_VALUE当成最大数组长度呢,也是可以的,在源码中可以看到,如果给定的最小容量大于MAX_ARRAY_SIZE,那么就可以使用Integer.MAX_VALUE。但是有可能会出现异常信息。
@Overridepublic boolean add(E e) {// 实现add数据add(e, elementData, size);return true;}private void add(E e, Object[] elementData, int s) {// 判断是否需要扩容if (s == elementData.length)// 扩容操作 将原来的数组的长度变为数组长度的1.5倍 length + (length >> 1)elementData = grow();elementData[s] = e; // 在数组的末尾添加数据size = s + 1;}private Object[] grow() {return grow(size + 1);}private Object[] grow(int minCapacity) {// 需要有防止溢出return Arrays.copyOf(this.elementData, newCapacity(minCapacity));}// 真正实现扩容的操作private int newCapacity(int minCapacity) {int oldCapacity = this.elementData.length;int newCapacity = oldCapacity + (oldCapacity >> 1); // 容量扩展为原来的1.5倍if((newCapacity - oldCapacity) <= 0) {if (this.elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)return Math.max(DEFAULT_CAPACITY, newCapacity);// 如果扩容数组的长度小于0 抛出异常信息 内存溢出if (newCapacity < 0)throw new OutOfMemoryError();return newCapacity;}// 此处是判断是否是需要Integer最大值作为数组的长度, 之所以平时使用最大长度为Integer.MAX_VALUE - 8 是因为虚拟机有时候需要有存储自己大小的空间return (newCapacity - MAX_ARRAY_SIZE) <= 0 ? newCapacity : hugeCapacity(minCapacity);}public boolean addAll(Collection<? extends E> c){Object[] o = c.toArray();int newArr = o.length;if (newArr == 0)return false;Object[] elementData;final int s;// 判断新的数组长度是否可以不用扩容就可以添加if(newArr > (elementData = this.elementData).length - (s = size)){elementData = grow(s+newArr);}System.arraycopy(o, 0, elementData, s, newArr);size = s + newArr;return true;}public boolean addAll(int index, Collection<? extends E> c){// 校验数组的长度是否 > indexrangeCheckForAdd(index);Object[] o = c.toArray();int newNum = o.length;Object[] elementData;final int s;// 判断新的数组长度是否可以不用扩容就可以添加if(newNum > (elementData = this.elementData).length - (s = size)){elementData = grow(s+newNum);}//记录数组插入位置到最后的数值,因为在指定位置插入数据 需要将指定位置到最后一个元素所在位置的数据整体向后移动int numMoved = s - index;if (numMoved > 0) {// 将原数组中从index开始到index+numMoved - 1 位置的元素 移动到index + newNum的位置上,中间的数组都是空的 为后面添加元素留出位置System.arraycopy(elementData, index, elementData, newNum + index, numMoved);}System.arraycopy(o, 0, elementData, index, newNum);size = s + newNum;return true;}