欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

关于List中的大大坑(二)

程序员文章站 2022-03-13 21:26:07
...

List的前两个坑:https://blog.csdn.net/Lucky_Boy_Luck/article/details/105715419
接下来是第三个坑:

1.3 不可变集合

        为了防止 List 集合被误操作,我们可以使用 Collections.unmodifiableList() 生成一个不可变(immutable)集合,进行防御性编程。

        这个不可变集合只能被读取,不能做任何修改,包括增加,删除,修改,从而保护不可变集合的安全。

举个小例子:

public class Test {

    public static void main(String[] args) {
        List<String> list = new ArrayList<>(Arrays.asList("dog", "cat"));
        List<String> unmodifiableList = Collections.unmodifiableList(list);

        unmodifiableList.add("pig");
        System.out.println(list);
        System.out.println(unmodifiableList);
    }
}

关于List中的大大坑(二)
        运行结果表明:程序运行在add()方法时,会抛出UnsupportedOperationException异常。这说明,确实生成了不可变集合。

查看源码:
首先调用Collections.unmodifiableList()方法:
关于List中的大大坑(二)
而UnmodifiableList是CollectionUtils类中的一个内部类,且实现了接口List。
关于List中的大大坑(二)
查看其中部分方法:
关于List中的大大坑(二)
发现set()/add()/remove()方法等都抛出UnsupportedOperationException异常。

所以:

unmodifiableList.add("pig");

程序运行到上面那条语句就会抛出UnsupportedOperationException异常

有趣事例

        如果你不小心改动原始 List,你就会发现这个不可变集合,竟然就变了。。。

        如,对上面个例子进行修改。修改原集合下标为0的元素,把“dog”修改为“goat”

public class Test {

    public static void main(String[] args) {
        List<String> list = new ArrayList<>(Arrays.asList("dog", "cat"));
        List<String> unmodifiableList = Collections.unmodifiableList(list);

        list.set(0, "goat");
        System.out.println(list.get(0));
        System.out.println(unmodifiableList.get(0));
    }
}

关于List中的大大坑(二)
运行结果:发现不可变集合的第一个元素竟然也变了。

查看源码:
首先调用Collections.unmodifiableList()方法:
关于List中的大大坑(二)
会调用Collections类中的内部类UnmodifiableList构造方法
关于List中的大大坑(二)
        在构造方法中,对其成员变量list赋值时,并没有新new 一个List,而是使用了原来的list。这其实跟之前的ArrayList类中的内部类 SubList 是同一个问题-------新集合底层实际使用了原始 List。

所以,对原集合的修改,会改变不可变集合的内容

        由于不可变集合所有修改操作都会报错,所以不可变集合不会产生任何改动,所以并不影响的原始集合。但是反过来,却不行,原始 List 随时都有可能被改动,从而影响不可变集合。

1.4 foreach 增加/删除元素大坑

这部分有在这篇文章中涉及到:Java中的fail-fast机制

转载

相关标签: javaSE