繁体   English   中英

不可修改的可修改对象列表

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM