探索JAVA不可变集合

 编写测试类

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没有,他们的数据结构也是有差别的)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值