[英]Unmodifiable List of modifiable objects
假设我们有一个List<List<String>>
并希望它完全不可修改。 简单地将它传递给Collection.unmodifiableList
是不够的,因为仍然可以修改内部列表。
我会采用以下方法:
List<List<String>> someList;
使其不可修改:
List<List<String>> tempList = new ArrayList<>();
for(List<String> strList : someList) {
tempList.add(Collections.unmodifiableList(strList));
}
List<List<String>> safeList = Collections.unmodifiableList(tempList);
这种方法可以吗?
只要您不保留对原始可修改列表的引用,此方法就可以正常工作。 此类引用可以修改由不可修改列表包装的列表。
实现不变性的方法是创建防御性副本。
每当将可变对象传递给您的方法时,您都会创建它的深层副本。 如果您想要最大的安全性,这应该是您做的第一件事,甚至在您检查有效性之前。
将列表包装到Collections.unmodifiableList()
中不会起作用,因为不能保证第三方不会修改基础列表。 换句话说,您无法控制实例。
创建列表的不可变副本的好方法是使用Google Guava的ImmutableList.copyOf()
方法,但请记住,您需要深层副本,因此您需要在主列表中创建列表的不可变副本。
每当您返回一个值时,您都会制作另一个防御性副本,以便对返回的对象的更改不会反映出来。 在这里,您可以在列表中使用不可修改的包装器(例如ImmutableList.of()
),因为您只保留对原始列表的唯一引用。
如果您同时执行这两项操作(在中途复制,复制/换行),您的代码将是安全和正确的。 任何其他解决方案,并没有这样的一般保证,您的代码可能或许多不正确。
我觉得它不起作用: -
List<List<String>> someList = new ArrayList<>();
List<String> l1 = new ArrayList<String>();
List<String> l2 = new ArrayList<String>();
l1.add("STR1");
l1.add("STR2");
l1.add("STR3");
l2.add("STR4");
l2.add("STR5");
l2.add("STR6");
someList.add(l1);
someList.add(l2);
List<List<String>> tempList = new ArrayList<>();
for(List<String> strList : someList) {
tempList.add(Collections.unmodifiableList(strList));
}
List<List<String>> safeList = Collections.unmodifiableList(tempList);
l1.add("STR7"); // The inner list reference is modified which causes the
safelist internal structure to get changed
for(List<String> safeInnerList : safeList) {
System.out.println(safeInnerList);
}
以下代码应该: -
List<List<String>> tempList = new ArrayList<>();
for(List<String> strList : someList) {
tempList.add(new ArrayList<>(strList));
}
List<List<String>> safeList = Collections.unmodifiableList(tempList);
这是对此的测试: -
List<List<String>> someList = new ArrayList<>();
List<String> l1 = new ArrayList<String>();
List<String> l2 = new ArrayList<String>();
l1.add("STR1");
l1.add("STR2");
l1.add("STR3");
l2.add("STR4");
l2.add("STR5");
l2.add("STR6");
someList.add(l1);
someList.add(l2);
List<List<String>> tempList = new ArrayList<>();
for(List<String> strList : someList) {
tempList.add(new ArrayList<>(strList));
}
List<List<String>> safeList = Collections.unmodifiableList(tempList);
l1.add("STR7"); // The inner list reference is modified this doesnot cause the safelist internal structure to get changed
for(List<String> safeInnerList : safeList) {
System.out.println(safeInnerList);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.