java - 具有 ArrayList 成员变量的不可变对象(immutable对象) - 为什么可以更改此变量?

标签 java object immutability member getter-setter

我有一个包含各种成员变量的类。有一个构造函数,有 getter 方法,但没有 setter 方法。事实上,这个对象应该是不可变的。

public class Example {
   private ArrayList<String> list; 
}

现在我注意到以下情况:当我使用 getter 方法获取变量列表时,我可以添加新值等等 - 我可以更改 ArrayList。当我下次为此变量调用 get() 时,将返回更改后的 ArrayList。怎么会这样?我没有再设置它,我只是在努力! 使用 String 这种行为是不可能的。那么这里有什么区别呢?

最佳答案

仅仅因为对列表的引用是不可变的并不意味着它引用的列表是不可变的。

即使将 list 设为 final,这也是允许的

// changing the object which list refers to
example.getList().add("stuff");

但是这不允许:

// changing list
example.list = new ArrayList<String>();   // assuming list is public

为了使列表不可变(也防止第一行),我建议你使用Collections.unmodifiableList :

public class Example {
    final private ArrayList<String> list;

    Example(ArrayList<String> listArg) {
        list = Collections.unmodifiableList(listArg);
    }
}

(请注意,这会创建一个不可修改的 ListView 。如果有人保留原始引用,那么仍然可以通过它修改列表。)


With a String this behaviour isnt possible. So what is the difference here?

这是因为 String 已经是不可变的(不可修改的),就像您将列表变成 unmodifiableList 时一样。

比较:

              String data structure  | List data structure
           .-------------------------+------------------------------------.
Immutable  | String                  | Collection.unmodifiableList(...)   |
-----------+-------------------------+------------------------------------|
Mutable    | StringBuffer            | ArrayList                          |
           '-------------------------+------------------------------------'

关于java - 具有 ArrayList 成员变量的不可变对象(immutable对象) - 为什么可以更改此变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6137224/

相关文章:

java - Java 中的客户端 SSL 证书 : PKIX path building failed

java - Java 中有没有办法找出扫描仪跳过的字符串?

c# - 有没有简单的方法来检查任何类实例的修改?

java - Java 中的类加载与对象创建

iterator - 如何从一个范围创建一个 Vec 并对其进行洗牌?

java - 如何将标签设置为 iText 列表

java - 如何在 response.sendRedirect() 之后发送 cookie?

javascript - 检查对象是否存在

javascript - 当我每次函数调用创建一个新的生成器时,为什么这个生成器函数包装器会消耗迭代器?

.net - 在 .NET 中表示不可变列表的最佳方式是什么?