一尘不染

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

java

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

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

现在我注意到了以下几点:当我使用getter方法获得变量列表时,可以添加新值,依此类推-
可以更改ArrayList。下次调用get()此变量时,将ArrayList返回更改的内容。怎么会这样?我没有再设置它,我只是在做它!使用String这种行为是不可能的。那么这里有什么区别?


阅读 136

收藏
2020-12-03

共1个答案

一尘不染

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

即使这样listfinal了也可以

// 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);
    }
}

(请注意,这将创建列表的不可修改视图。如果有人坚持使用原始参考,则仍可以通过该列表来修改列表。)


使用字符串,此行为是不可能的。 那么这里有什么区别?

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

比较:

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