- Collections是集合工具类
- Arrays是数组工具类
Arrays.asList()得到的List只可查可改;Collections.unmodifiableList()得到的List只可查
源码分析
1、Arrays.asList()
@SafeVarargs
@SuppressWarnings("varargs")
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
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 E get(int index) {
return a[index];
}
@Override
public E set(int index, E element) {
E oldValue = a[index];
a[index] = element;
return oldValue;
}
...
}
源码分析:只截取了部分用于分析的源码
Arrays.asList(T... a)返回了一个新的ArrayList对象。从源码中来看,该ArrayList是Arrays自身的一个静态内部类。它的class声明为
private static class ArrayList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable
从class声明来看,Arrays.asList()获得的List是支持快速访问,并且是可序列化的。
为什么说Arrays.asList()获得的List只能用来查看元素和修改元素呢。来看静态内部类ArrayList的字段和构造器
private final E[] a; ArrayList(E[] array) { a = Objects.requireNonNull(array); }
ArrayList中用于保存元素的数组a被声明为final,表示a指向的对象地址是不能更改的,而List中增加或删除元素涉及到数组大小的改变以及元素的移动,这种结构性变化必然会导致a指向的对象地址发生改变。所以源码中只有get()和set()方法,并没有add()和remove()方法,故而说Arrays.asList()获得的List只能用于查看元素和修改元素。
2、Collections.unmodifiableList()
public static <T> List<T> unmodifiableList(List<? extends T> list) {
return (list instanceof RandomAccess ?
new UnmodifiableRandomAccessList<>(list) :
new UnmodifiableList<>(list));
}
static class UnmodifiableList<E> extends UnmodifiableCollection<E>
implements List<E> {
private static final long serialVersionUID = -283967356065247728L;
final List<? extends E> list;
UnmodifiableList(List<? extends E> list) {
super(list);
this.list = list;
}
public E get(int index) {return list.get(index);}
public E set(int index, E element) {
throw new UnsupportedOperationException();
}
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
public E remove(int index) {
throw new UnsupportedOperationException();
}
...
}
static class UnmodifiableRandomAccessList<E> extends UnmodifiableList<E>
implements RandomAccess
{
UnmodifiableRandomAccessList(List<? extends E> list) {
super(list);
}
public List<E> subList(int fromIndex, int toIndex) {
return new UnmodifiableRandomAccessList<>(
list.subList(fromIndex, toIndex));
}
private static final long serialVersionUID = -2542308836966382001L;
private Object writeReplace() {
return new UnmodifiableList<>(list);
}
}
源码分析:源码有点多,这里只贴出要用到的部分源码
Collections.unmodifiableList()返回一个对象,对象中组合有一个List对象,这里用到了RandomAccess,若原来的List是支持快速访问(即实现了RandomAccess)的,那就返回一个UnmodifiableRandomAccessList对象,否则返回的是UnmodifiableList对象。但是在源码中UnmodifiableRandomAccessList并没有什么独特的地方,一切都是依靠UnmodifiableList建立起来的,所以UnmodifiableRandomAccessList在这里也应该理解为是一个标识,标识着自己是支持快速访问的。
所以说根本的还是要看UnmodifiableList类,在UnmodifiableList源码中
public E get(int index) {return list.get(index);} public E set(int index, E element) { throw new UnsupportedOperationException(); } public void add(int index, E element) { throw new UnsupportedOperationException(); } public E remove(int index) { throw new UnsupportedOperationException(); }
除了get()之外,set()、add()、remove()都没有具体的实现,而是直接抛出一个异常,表示该类不支持set()、add()、remove()。所以说Collections.unmodifiableList()返回的List只允许访问而不允许修改,删除,增加。
不仅是Collections.unmodifiableList(),包括Collections.unmodifiableMap(),Collections.unmodifiableSet()都是只允许访问而不允许修改,删除,增加。