java.util.Arrays$ArrayList
(下文:Arrays$ArrayList
)是java.util.Arrays
的私有静态内部类,他实现的接口,继承的父类几乎和java.util.ArrayList
(下文:ArrayList
)相同,既然是私有的,那么日常应该是咱们少关注的地方。本文尝试对比一两个他们之间的不一样点。java
构造拥有三个字符串的List
,ArrayList
数组
List<String> lb = new ArrayList<>(3); lb.add("a"); lb.add("b"); lb.add("c");
Arrays$ArrayList
ide
List<String> la = Arrays.asList("a", "b", "c"); //源码 public static <T> List<T> asList(T... a) { return new ArrayList<>(a); }
二者都知足了需求,后者看起来比前者简洁,除此以外二者还有什么不一样呢。this
支持的操做,spa
lb.add("d") lb.remove("d")
不支持的操做,这将会抛出异常java.lang.UnsupportedOperationException
code
la.add("d") la.remove("d")
可见Arrays$ArrayList
不容许增长也不容许删除。blog
在Arrays$ArrayList
类,
首先并无override父类的add
方法,因此这个方法来自他的父类AbstractList
;
看AbstractList
中的add
方法继承
public boolean add(E e) { add(size(), e); return true; } public void add(int index, E element) { throw new UnsupportedOperationException(); }
最终调用的方法抛出了异常UnsupportedOperationException
。
相比较ArrayList
接口
public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } public void add(int index, E element) { rangeCheckForAdd(index); ensureCapacityInternal(size + 1); // Increments modCount!! System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; }
这两个方法都在ArrayList
中实现了,或者扩容而后在尾部插入,或者扩容、移动数组元素,而后插入到指定的下标位置。ip
Arrays$ArrayList
的remove(Object)
方法继承自AbstractList
的父类AbstractCollection
,其中
public boolean remove(Object o) { Iterator<E> it = iterator(); if (o==null) { while (it.hasNext()) { if (it.next()==null) { it.remove(); return true; } } } else { while (it.hasNext()) { if (o.equals(it.next())) { it.remove(); return true; } } } return false; }
这里使用了迭代器的方式进行删除,看这个方法的注释
若是这个迭代器没有实现remove
方法的话,那么这整个方法也将要抛出UnsupportedOperationException
异常的。
在AbstractCollection
中iterator
是一个抽象方法,之于Arrays$ArrayList
,这个方法实现的位置仍是在AbstractList
,
public Iterator<E> iterator() { return new Itr(); } private class Itr implements Iterator<E> { //...省略 public void remove() { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { AbstractList.this.remove(lastRet); if (lastRet < cursor) cursor--; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException e) { throw new ConcurrentModificationException(); } } }
到这里咱们发现AbstractList
实现了AbstractCollection
的iterator
方法,并且返回的迭代器也实现了remove
方法,不是上文提到的注释那种状况。可是为何删除动做仍是不容许的呢?
具体这个迭代器的remove
方法,
AbstractList.this.remove(lastRet);
可见迭代器最终也是调用容器类的remove
方法的,那么Arrays$ArrayList
没有实现remove
方法,而AbstractList
的remove
方法,以下
public E remove(int index) { throw new UnsupportedOperationException(); }
所以,即便在AbstractList
中使用迭代器进行删除操做,但因为Arrays$ArrayList
没有实现remove
且继承的remove
抛出UnsupportedOperationException
异常,最终在Arrays$ArrayList
是不容许删除操做的。
值得注意的是,AbstractList
的迭代器是否要调用remove(int)
方法是由要删除的目标是否数组的元素决定的,若是不存在这样的元素,则下面的代码并不会出现异常,
List<String> la = Arrays.asList("a", "b", "c"); la.remove("e");