本博客转载自:https://blog.csdn.net/maywehe/article/details/52553954
写demo的时候,为了避免用list.add方法,特意写了个数组然后转换成list。一开始以为转换成的list就是实现了AbstractList的通用的List, 比如ArrayList或者LinkedList等。 当调用add方法的时候, 奇怪的事情发生了。
String[] arrays = new String[] { "1", "2", "3" };
List list = Arrays.asList(arrays);
list.add("4");
抛异常:
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)
at java.util.AbstractList.add(AbstractList.java:108)
at com.maywe.list.Demo.main(Demo.java:43)
List 调用add方法是最普遍不过的场景,怎么会抛异常呢? 赶快去研究下源码。
java.util.Arrays$ArrayList 源码($表示内部类的意思,下面的源码是Arrays内部类ArrayList 的类型定义源码,在java.util.Arrays.class文件中)
private static class ArrayList extends AbstractListimplements RandomAccess, java.io.Serializable
{private static final long serialVersionUID = -2764017481108945198L;privatefinal E[] a;
ArrayList(E[] array) {if (array==null)throw newNullPointerException();
a=array;
}public intsize() {returna.length;
}publicObject[] toArray() {returna.clone();
}public T[] toArray(T[] a) {int size =size();if (a.length
(Class extends T[]>) a.getClass());
System.arraycopy(this.a, 0, a, 0, size);if (a.length >size)
a[size]= null;returna;
}public E get(intindex) {returna[index];
}public E set(intindex, E element) {
E oldValue=a[index];
a[index]=element;returnoldValue;
}public intindexOf(Object o) {if (o==null) {for (int i=0; i
}else{for (int i=0; i
}return -1;
}publicboolean contains(Object o) {return indexOf(o) != -1;
}
}
的确是实现了AbstractList,但是没有实现add方法, 在看看AbstractList的add方法:
publicboolean add(E e) {
add(size(), e);return true;
}public void add(intindex, E element) {throw newUnsupportedOperationException();
}
UnsupportedOperationException 就是怎么抛出来的。(解释:List list = Arrays.asList(arrays)语句中,Arrays.asList(arrays)的返回值(Arrays$ArrayList类型)被向上为list。当调用add(E e)方法的时候,会直接调用Arrays$ArrayList类的add(int index, E element)方法,由于Arrays$ArrayList类没有重写add(size(), e)方法,所以会调用基类(AbstractList)的add(int index, E element)方法,所以会抛出UnsupportedOperationException异常。由此可知,如果想不报异常,Arrays$ArrayList类应该重写add(E e)方法或者add(int index, E element)方法)
所以java.util.Arrays$ArrayList只能在不超过capacity的情况下调用set设置元素,不能增加元素。
顺便研究了下java.util..ArrayList的add方法。
publicboolean add(E e) {
ensureCapacityInternal(size+ 1); //Increments modCount!!
elementData[size++] =e;return true;
}
在List的最后Append新元素,capacity增加一个
public void add(intindex, E element) {
rangeCheckForAdd(index);//判断index是否小于0或者大于数组长度,
ensureCapacityInternal(size+ 1); //Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size-index);
elementData[index]=element;
size++;
}
在index指定的位置增加元素E, 同时index右边的(索引>index) 所有元素右移;
如果参数index大于当前的size会抛出异常,因为capacity只是增加一;
因为存在“右移”操作,建议没有必要的情况下调用List#add(E e)即可,避免不必要的“右移”操作
demo 代码:
String[] arrays = new String[] { "1", "2", "3"};
List list =Arrays.asList(arrays);
System.out.println(list);
System.out.println(list.getClass());
List list2 = new ArrayList(list);
list2.add(0, "0");
System.out.println(list2);
System.out.println(list2.getClass());
结果输出:
[1, 2, 3]classjava.util.Arrays$ArrayList
[0, 1, 2, 3]class java.util.ArrayList