我有一个关于创建不可变类的查询。以下是我考虑的要点:
- 完成类(class)
- 使所有成员成为最终成员,在静态 block 或构造函数中显式设置它们
- 将所有成员设为私有(private)
- 没有修改状态的方法
- 要非常小心地限制对可变成员组件的访问(记住该字段可能是最终的,但对象仍然是可变的。即私有(private)最终日期 imStillMutable)- 请参阅防御性复制或其同类复制构造函数以获取更多信息。
但是我根本没有完全理解 5 点,你能给我建议或给我一个例子,在那个例子中 5 点是清楚的吗?
最佳答案
第 5 点表明,任何时候您有任何方法返回与可变对象有关的东西时,您都希望创建一个独立于私有(private)状态的副本。例如:
public final class Foo
{
private final List<String> strings;
public Foo(List<String> strings)
{
// Defensive copy on construction. Protects from constructing
// code mutating the list.
this.strings = new ArrayList<String>(strings);
}
public List<String> getStrings()
{
// Defensive copy on read. Protects from clients mutating the list.
return new ArrayList<String>(strings);
}
}
请注意,仅当状态可变时才需要防御性复制。例如,如果您使用 ImmutableList
(例如来自 Guava )作为上述类中的状态,您需要在构造时创建一个新列表(除非输入也是 ImmutableList
)但 不是 在 getStrings
中.
另请注意,在本例中 String
是不可变的,所以我们不需要复制每个字符串。如果这是 List<StringBuilder>
我们需要创建一个新列表和每个元素的新副本作为防御副本的一部分。如您所见,当您的所有状态也不可变时,生活会变得更简单。
关于java - 关于不可变类防御性复制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12000655/