原文网址:Java的List之坑系列--Collections#unmodifiableList仍然可变_IT利刃出鞘的博客-CSDN博客
简介
说明
本文介绍Collections#unmodifiableList的坑:本不可变的集合却被改变了。
Collections#unmodifiableList是保护集合的,让集合不可变,本文介绍它被改变的情况。
Collections#unmodifiableList简介
为了防止 List 集合被误操作,可用Collections#unmodifiableList生成一个不可变(immutable)集合,进行防御性编程。这个不可变集合只能被读取,不能做写操作,包括增加,删除,修改,从而保护不可变集合的安全。
原理:返回的集合没有实现增删改的方法。
示例:
-
package org.example.a;
-
-
import java.util.ArrayList;
-
import java.util.Arrays;
-
import java.util.Collections;
-
import java.util.List;
-
-
public
class
Demo {
-
public
static
void
main
(String[] args) {
-
List<String> list =
new
ArrayList<>(Arrays.asList(
"one",
"two",
"tree"));
-
List<String> unmodifiableList = Collections.unmodifiableList(list);
-
// 以下三行都会抛出UnsupportedOperationException 异常
-
unmodifiableList.add(
"four");
-
unmodifiableList.remove(
1);
-
unmodifiableList.set(
0,
"test");
-
}
-
}
结果
-
Exception in thread
"main" java.lang.UnsupportedOperationException
-
at java.util.Collections
$UnmodifiableCollection.
add(Collections.
java:
1055)
-
at org.example.a.Demo.
main(Demo.
java:
12)
问题复现
如果使用不当,Collections#unmodifiableList操作后的List也是可能会被改变的。
代码
-
package org.example.a;
-
-
import java.util.ArrayList;
-
import java.util.Arrays;
-
import java.util.Collections;
-
import java.util.List;
-
-
public
class
Demo {
-
public
static
void
main
(String[] args) {
-
List<String> list =
new
ArrayList<>(Arrays.asList(
"one",
"two",
"tree"));
-
List<String> unmodifiableList = Collections.unmodifiableList(list);
-
list.set(
0,
"one_modified");
-
System.out.println(unmodifiableList.get(
0));
-
}
-
}
执行结果
one_modified
可见,被修改了!
原因分析
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;
-
}
-
...
-
}
跟前边subList方法一样的情况:新集合底层实际使用(引用)了原始 List。
解决方法
法1:JDK1.9的List#of 方法
-
List<String> list =
new
ArrayList<>(Arrays.asList(
"one",
"two",
"three"));
-
List<String> unmodifiableList = List.of(list.toArray(
new
String[]{}));
法2:Guava包的ImmutableList
-
List<String> list =
new
ArrayList<>(Arrays.asList(
"one",
"two",
"three"));
-
List<String> unmodifiableList = ImmutableList.copyOf(list);
转载:https://blog.csdn.net/feiying0canglang/article/details/127651732
查看评论