当前位置: 首页 > 面试题库 >

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

仇睿
2023-03-14
问题内容

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

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

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


问题答案:

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

即使这样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                          |
           '-------------------------+------------------------------------'


 类似资料:
  • 我想出了这个类: 这里是用法: 问题: 为什么使用作为返回表达式编译得很好(Z不是instexpr)。 如何调用和方法的对象() ? 中的行为在编译器中是不同的。MSVC可以使用作为模板参数进行编译,而GCC(IdeOne)不会编译它。 对于一个编译器来说< code>constexpr GetX是真正的< code>constexpr,但是对于另一个编译器来说,如果涉及到< code>X Z就不

  • 问题内容: 我有一个班级和年龄段。但是,当我更改对象的年龄时,该类的所有其他对象也会更改。 有人可以帮助解决这个问题吗? 问题答案: 静态变量 是 类变量, 因此从变量声明中删除为: 根据java docs: 在声明中具有static修饰符的字段称为静态字段或类变量。它们与类关联,而不与任何对象关联。该类的每个实例共享一个类变量,该变量位于内存中的一个固定位置。

  • 所以我读了关于HashMap的文章。有人曾指出: 我不太明白...为什么?

  • 这个问题与前一个问题相关,在前一个问题中,我们注意到init捕获lambdas与Boost的范围和迭代器不兼容,因为一些相当模糊且嵌套很深的故障可能很难通过破解Boost来解决。射程源。 接受的答案建议将lambda存储在对象中。为了避免潜在的函数调用开销,我编写了两个函数对象,可以作为潜在的解决方法。它们在下面的代码中被称为和 不使用和编译行,并正确打印行的的实例。 然而,标准草案提到 5.1.

  • 问题内容: 我正在努力使可变对象与不可变对象有关。使用可变对象会带来很多负面影响(例如,从方法中返回字符串数组),但是我很难理解它的负面影响。使用可变对象的最佳实践是什么?您是否应尽可能避免使用它们? 问题答案: 好吧,这有几个方面。 没有参考身份的可变对象会在奇数时间导致错误。例如,考虑使用基于值的方法的 : 当实例用作键时,实例在映射中“丢失”,因为实例和相等性基于可变值。这些值在映射之外更改

  • 问题内容: 我将如何完成? 我敢肯定有一个非常明显的答案。现在只是在逃避我。 问题答案: 是的,他们可以使用相同的名称。但是,要引用实例变量,您需要使用前缀: