编写测试类
package com.zlyx.demo.test;
import java.util.Collections;
import java.util.List;
import com.zlyx.easycore.list.EasyList;
import com.zlyx.easycore.map.Maps;
import com.zlyx.easycore.tool.Console;
public class Test {
public static void main(String[] args) {
Console.log(Maps.newHashMap("123", "456", "456", "789"));
EasyList<String> list = EasyList.newList("123", "456", "456", "789");
Console.log(list);
List<String> list2 = Collections.unmodifiableList(list);
list2.add("21321");
System.out.println(list2);
}
}
运行结果:
可以看到,抛异常了噻。小手一抖,赶紧点开源码看看咋回事:
public boolean add(E e) {
throw new UnsupportedOperationException();
}
这啥?你在逗我?带着疑惑上翻翻下找找,找到了这段代码:
static class UnmodifiableCollection<E> implements Collection<E>, Serializable {
private static final long serialVersionUID = 1820017752578914078L;
final Collection<? extends E> c;
UnmodifiableCollection(Collection<? extends E> c) {
if (c==null)
throw new NullPointerException();
this.c = c;
}
public int size() {return c.size();}
public boolean isEmpty() {return c.isEmpty();}
public boolean contains(Object o) {return c.contains(o);}
public Object[] toArray() {return c.toArray();}
public <T> T[] toArray(T[] a) {return c.toArray(a);}
public String toString() {return c.toString();}
public Iterator<E> iterator() {
return new Iterator<E>() {
private final Iterator<? extends E> i = c.iterator();
public boolean hasNext() {return i.hasNext();}
public E next() {return i.next();}
public void remove() {
throw new UnsupportedOperationException();
}
@Override
public void forEachRemaining(Consumer<? super E> action) {
// Use backing collection version
i.forEachRemaining(action);
}
};
}
public boolean add(E e) {
throw new UnsupportedOperationException();
}
public boolean remove(Object o) {
throw new UnsupportedOperationException();
}
public boolean containsAll(Collection<?> coll) {
return c.containsAll(coll);
}
public boolean addAll(Collection<? extends E> coll) {
throw new UnsupportedOperationException();
}
public boolean removeAll(Collection<?> coll) {
throw new UnsupportedOperationException();
}
public boolean retainAll(Collection<?> coll) {
throw new UnsupportedOperationException();
}
public void clear() {
throw new UnsupportedOperationException();
}
// Override default methods in Collection
@Override
public void forEach(Consumer<? super E> action) {
c.forEach(action);
}
@Override
public boolean removeIf(Predicate<? super E> filter) {
throw new UnsupportedOperationException();
}
@SuppressWarnings("unchecked")
@Override
public Spliterator<E> spliterator() {
return (Spliterator<E>)c.spliterator();
}
@SuppressWarnings("unchecked")
@Override
public Stream<E> stream() {
return (Stream<E>)c.stream();
}
@SuppressWarnings("unchecked")
@Override
public Stream<E> parallelStream() {
return (Stream<E>)c.parallelStream();
}
}
搜嘎,感情,调用Collections.unmodifiableList()方法,给我返回了这么个玩意?我不信,我要去找找这个方法里都做了啥:
public static <T> List<T> unmodifiableList(List<? extends T> list) {
return (list instanceof RandomAccess ?
new UnmodifiableRandomAccessList<>(list) :
new UnmodifiableList<>(list));
}
嗯?大哥,你这是在干啥啊?咋搞不懂了?UnmodifiableRandomAccessList和UnmodifiableList这两玩意干啥的啊?赶紧看看UnmodifiableRandomAccessList的源码:
static class UnmodifiableRandomAccessList<E> extends UnmodifiableList<E> implements RandomAccess{
}
发现它继承了UnmodifiableList并且实现了一个从来没见过的RandomAccess接口。所以答案就在UnmodifiableList类里了:
static class UnmodifiableList<E> extends UnmodifiableCollection<E> implements List<E> {
}
所以,UnmodifiableList是UnmodifiableCollection的子类?换言之,调用Collections.unmodifiableList()方法后,把参数list偷梁换柱,变成了UnmodifiableCollection了?那还等什么,答案都在UnmodifiableCollection里了。结果,还真找到了原因:
final Collection<? extends E> c;
UnmodifiableCollection(Collection<? extends E> c) {
if (c==null)
throw new NullPointerException();
this.c = c;
}
原来,在Collections.unmodifiableList()方法中实例化UnmodifiableRandomAccessList或UnmodifiableList时,会调用UnmodifiableCollection的构造方法,将参数list设为被final修饰的属性c的值,然后,就不可变了。以为被final修饰的属性只能在最开始被赋值一次。
除了list,Collections还提供了一下方法分别将Collection、Map、Set转换为不可变的对象。
那么问题来了,UnmodifiableRandomAccessList和UnmodifiableList的区别是啥呢?为啥还要分开判断?这就要去理解RandomAccess接口的作用了(小提示:ArrayList实现了RandomAccess接口,而LinkList没有,他们的数据结构也是有差别的)。