我有一个关于创建一个不可变类的查询。 以下是我拿在考虑几点:
- 使课堂最后
- 让所有成员最终,将它们明确,在静态块,或在构造函数
- 使所有成员私人
- 没有修饰状态的方法
- 要格外小心,以限制访问可变梁构件(记住该领域可能是最终的,但对象仍然可以是可变的,即私人最终日期imStillMutable。) - 参见防守复制或它的更多信息表妹拷贝构造函数。
但我不完全理解的5点全部,你可以请指教或告诉我一个例子,其中的5点在这个例子清楚了吗?
我有一个关于创建一个不可变类的查询。 以下是我拿在考虑几点:
但我不完全理解的5点全部,你可以请指教或告诉我一个例子,其中的5点在这个例子清楚了吗?
5点建议,你有这将返回的东西做一个可变对象的任何方法的任何时候,你想创建一个副本是独立的私有状态的。 例如:
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
在上面的类(如番石榴)作为状态,你需要创建一个建设新的列表(除非输入也是ImmutableList
),但不是在getStrings
。
另外请注意,在这种情况下, String
是不变的,所以我们并不需要每个字符串复制。 如果这是一个List<StringBuilder>
我们需要创建一个新的列表,每个元素的新副本的副本防守的一部分。 正如你所看到的,当你所有的状态是不可变的太的生活变得更简单。
final
意味着指示器不能指向的另一参考。 例如:
final Object obj = new Object();
obj = new Object(); //Invalid
但final
并不妨碍modifiying对象:
obj.setWhatever("aaa"); //Perfectly valid
如果你还没有限制访问的成员,那么任何人都可以获取对象并对其进行修改。
例如: yourClass.getObject().setWhatever("aaa").
防守复制是指getObject()
不会直接返回对象,但它会使它的一个副本,然后返回。 如果这样,来电者修改了返回的对象,也不会修改类的创始成员。