我有一类具有各种成员变量的类。有一个构造函数,有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);
}
}
(请注意,这将创建列表的不可修改视图。如果有人坚持使用原始参考,则仍可以通过该列表来修改列表。)
使用字符串,此行为是不可能的。 那么这里有什么区别?
这是因为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.
问题内容: 我正在努力使可变对象与不可变对象有关。使用可变对象会带来很多负面影响(例如,从方法中返回字符串数组),但是我很难理解它的负面影响。使用可变对象的最佳实践是什么?您是否应尽可能避免使用它们? 问题答案: 好吧,这有几个方面。 没有参考身份的可变对象会在奇数时间导致错误。例如,考虑使用基于值的方法的 : 当实例用作键时,实例在映射中“丢失”,因为实例和相等性基于可变值。这些值在映射之外更改
问题内容: 我将如何完成? 我敢肯定有一个非常明显的答案。现在只是在逃避我。 问题答案: 是的,他们可以使用相同的名称。但是,要引用实例变量,您需要使用前缀: