Java容器探索-为何Arrays.asList()方法产生的List调用Iterator.remove()报错,new ArrayList()产生的ArrayList就能正常移除

1. new ArrayList产生的ArrayList是java.util.ArrayList

  1. ArrayList继承了抽象类AbstractList:
public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
  1. ArrayList有个内部类实现了Iterator,该内部类实现了remove()方法
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();
        }
    }
}
  1. ArrayList重新了AbstractList的public E remove(int index)方法,说白了就是数组的重新copy过程
public E remove(int index) {
    rangeCheck(index);

    modCount++;
    E oldValue = elementData(index);

    int numMoved = size - index - 1;
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved);
    elementData[--size] = null; // clear to let GC do its work

    return oldValue;
}

2. Arrays.asList()产生的ArrayList是Arrays的一个内部类

  1. Arrays.asList()通过new自己内部类ArrayList返回一个List
public static <T> List<T> asList(T... a) {
    return new ArrayList<>(a);
}
  1. Arrays内部类ArrayList继承了AbstractList
private static class ArrayList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable{
private static final long serialVersionUID = -2764017481108945198L;
private final E[] a;

ArrayList(E[] array) {
    a = Objects.requireNonNull(array);
}

@Override
public int size() {
    return a.length;
}

@Override
public Object[] toArray() {
    return a.clone();
}

@Override
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
    int size = size();
    if (a.length < size)
        return Arrays.copyOf(this.a, size,
                             (Class<? extends T[]>) a.getClass());
    System.arraycopy(this.a, 0, a, 0, size);
    if (a.length > size)
        a[size] = null;
    return a;
}

@Override
public E get(int index) {
    return a[index];
}

@Override
public E set(int index, E element) {
    E oldValue = a[index];
    a[index] = element;
    return oldValue;
}

@Override
public int indexOf(Object o) {
    E[] a = this.a;
    if (o == null) {
        for (int i = 0; i < a.length; i++)
            if (a[i] == null)
                return i;
    } else {
        for (int i = 0; i < a.length; i++)
            if (o.equals(a[i]))
                return i;
    }
    return -1;
}
  1. 可以发现该内部类没有重写AbstractList的public E remove(int index)方法。所以调用该方法,其实就是调用AbstractList的该方法,看看该方法源码。
public E remove(int index) {
    throw new UnsupportedOperationException();
}

到此已经彻底明白为什么Arrays.asList()方法产生的List调用Iterator.remove()会报错了

3. 总结

归根到底,这两种方式产生的ArrayList就不是一个类,一个是Arrays的内部类,该类remove方法直接调用AbstractList的实现;另一个是java.util.ArrayList该类重写了remove和remove(int index)方法。

猜你喜欢

转载自blog.csdn.net/qwqw3333333/article/details/104689635