修改了使数组不可变的代码,但是在某些地方出错了,就像在代码中一样,当为ImmutableClassWithArray创建对象时,列表是使用给定数组初始化的。在getter内部,返回不可修改的列表,并将其转换为数组。之后,将修改数组。即使在构造函数被调用之后,数组已经被更改,意味着在列表已经初始化了一些值之后,最终的数组仍然反映了更新后的值。
public final class ImmutableClassWithArray {
private final Integer[] arr= {1,2,3,4};
List<Integer> list;
public ImmutableClassWithArray() {
this.list = Collections.unmodifiableList(Arrays.asList(arr));
}
public Integer[] getArr() {
return (Integer[]) this.list.toArray();
}
public static void main(String[] args) {
ImmutableClassWithArray ob = new ImmutableClassWithArray();
System.out.println("list value after copying array "+ob.list.get(2));
ob.arr[2]=5;
System.out.println("arr value after modified "+ob.arr[2]);
Integer[] a = ob.getArr();
System.out.println("a value - "+a[2]);
}
}
输出:->
复制数组3后的列表值
修改5后的arr值
一个值-5
Integer [] a = ob.getArr();应该返回数组的原始值,因为列表在更改值之前已经初始化。 但是,就像在输出中获得“一个值-5”一样,它应该是“一个值-3”。
谢谢!!!!
答案 0 :(得分:2)
请注意,不可修改与不可变不同。
对不变的东西,您无能为力,无法修改其状态。
您无法通过该事物的界面通过不可修改的事物来修改其状态。但是,如果您可以通过其他方式访问数据,例如您可以直接访问支持数组,可以对其进行修改,并通过不可修改的列表来观察更改。
答案 1 :(得分:1)
制作数组final
不会使其内容不变。只是说数组引用本身不能更改。
将其包装在unmodifiableList
中仅意味着引用该List
的人不能通过该List
接口进行更新 。
但是,如果您可以访问数组(在执行操作时),您仍然可以更改其内容,并且无法修改的视图将相应地更新(它只是包装器,而不是副本)。
如果要保护数组的内容,则必须关闭对其的所有访问(将其设为私有,并且不允许对象的任何方法以任何方式更改其值。)
要注意的另一件事是,您在对阵列进行更新后正在执行Integer[] a = ob.getArr();
。因此,使用toArray()
从不可修改列表创建的新数组实例实际上反映了更新后的值。