关于List中的大大坑(二)
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);
}
}
运行结果表明:程序运行在add()方法时,会抛出UnsupportedOperationException异常。这说明,确实生成了不可变集合。
查看源码:
首先调用Collections.unmodifiableList()方法:
而UnmodifiableList是CollectionUtils类中的一个内部类,且实现了接口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));
}
}
运行结果:发现不可变集合的第一个元素竟然也变了。
查看源码:
首先调用Collections.unmodifiableList()方法:
会调用Collections类中的内部类UnmodifiableList构造方法
在构造方法中,对其成员变量list赋值时,并没有新new 一个List,而是使用了原来的list。这其实跟之前的ArrayList类中的内部类 SubList 是同一个问题-------新集合底层实际使用了原始 List。
所以,对原集合的修改,会改变不可变集合的内容
由于不可变集合所有修改操作都会报错,所以不可变集合不会产生任何改动,所以并不影响的原始集合。但是反过来,却不行,原始 List 随时都有可能被改动,从而影响不可变集合。
1.4 foreach 增加/删除元素大坑
这部分有在这篇文章中涉及到:Java中的fail-fast机制
上一篇: leetcode:那些年我遇到过的编程题010:按摩师
下一篇: 深入了解CORS