Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/363.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 可修改对象的不可修改列表_Java_List_Unmodifiable - Fatal编程技术网

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

Java 可修改对象的不可修改列表,java,list,unmodifiable,Java,List,Unmodifiable,假设我们有一个列表,希望它完全不可修改。仅将其传递给集合。不可修改列表是不够的,因为内部列表仍然可以修改 我会采用以下方法: List<List<String>> someList; List-someList; 使其不可修改: List<List<String>> tempList = new ArrayList<>(); for(List<String> strList : someList) { tempL

假设我们有一个
列表
,希望它完全不可修改。仅将其传递给
集合。不可修改列表
是不够的,因为内部列表仍然可以修改

我会采用以下方法:

List<List<String>> someList;
List-someList;
使其不可修改:

List<List<String>> tempList = new ArrayList<>();
for(List<String> strList : someList) {
    tempList.add(Collections.unmodifiableList(strList));
}
List<List<String>> safeList = Collections.unmodifiableList(tempList);
List templast=new ArrayList();
for(列表strList:someList){
add(Collections.unmodifiableList(strList));
}
列表安全列表=集合。不可修改列表(模板列表);

这种方法行吗?

只要不保留对原始、可修改列表的引用,这种方法就应该有效。此类引用可能会修改由不可修改列表包装的列表。

实现不可变性的方法是创建防御性副本。

数据输入 每当一个可变对象被传递给您的方法时,您都会创建它的深层副本。这应该是您要做的第一件事,即使在您检查有效性之前,如果您想要最大的安全性

将列表包装到集合中。不可修改列表()在这里不起作用,因为无法保证基础列表不会被第三方修改。换句话说,您无法控制该实例

创建列表的不可变副本的一个好方法是使用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-someList=new-ArrayList();
列表l1=新的ArrayList();
列表l2=新的ArrayList();
l1.添加(“STR1”);
l1.添加(“STR2”);
l1.添加(“STR3”);
l2.添加(“STR4”);
l2.添加(“STR5”);
l2.添加(“STR6”);
someList.add(l1);
添加(l2);
List templast=new ArrayList();
for(列表strList:someList){
add(Collections.unmodifiableList(strList));
}
列表安全列表=集合。不可修改列表(模板列表);
l1.添加(“STR7”);//内部列表引用被修改,从而导致
要更改的安全列表内部结构
对于(列表safeInnerList:safeList){
System.out.println(安全内部列表);
}

以下代码应该可以:-

            List<List<String>> tempList = new ArrayList<>();
            for(List<String> strList : someList) {
                tempList.add(new ArrayList<>(strList));
            }
            List<List<String>> safeList = Collections.unmodifiableList(tempList);
List templast=new ArrayList();
for(列表strList:someList){
添加(新数组列表(strList));
}
列表安全列表=集合。不可修改列表(模板列表);
下面是对这一点的测试:-

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);
        }
List-someList=new-ArrayList();
列表l1=新的ArrayList();
列表l2=新的ArrayList();
l1.添加(“STR1”);
l1.添加(“STR2”);
l1.添加(“STR3”);
l2.添加(“STR4”);
l2.添加(“STR5”);
l2.添加(“STR6”);
someList.add(l1);
添加(l2);
List templast=new ArrayList();
for(列表strList:someList){
添加(新数组列表(strList));
}
列表安全列表=集合。不可修改列表(模板列表);
l1.添加(“STR7”);//内部列表引用已修改,这不会导致safelist内部结构发生更改
对于(列表safeInnerList:safeList){
System.out.println(安全内部列表);
}

我认为它应该可以很好地工作。将它包装在自己的容器中有什么不对?当然,如果列表中包含可变对象(例如,StringBuilder和String),那么这些对象仍然是可变的。从类/需求的角度看,您想做什么。这看起来确实有更好的方法来完成您想做的事情。列表是对象的私有成员。此对象应该能够修改列表。但是其他对象应该能够读取列表。您的目标是正确的。上面我分享的代码确实验证了你的第一点