Java 关于不可变的类
我有一个关于创建不可变类的问题。以下是我考虑的几点:Java 关于不可变的类,java,immutability,defensive-copy,Java,Immutability,Defensive Copy,我有一个关于创建不可变类的问题。以下是我考虑的几点: 期末考试 使所有成员为最终成员,在静态块或构造函数中显式设置它们 将所有成员保密 没有修改状态的方法 要非常小心地限制对可变成员组件的访问(记住字段可能是final,但对象仍然可以是可变的。即private final Date imStillMutable)-有关更多信息,请参阅防御性复制或其同类复制构造函数 但是我根本不理解5点,你能告诉我或给我一个例子,在这个例子中5点是清楚的吗?final表示指针不能指向另一个引用。 例如: fin
但是我根本不理解5点,你能告诉我或给我一个例子,在这个例子中5点是清楚的吗?
final
表示指针不能指向另一个引用。
例如:
final Object obj = new Object();
obj = new Object(); //Invalid
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);
}
}
但是final
不会阻止修改对象:
obj.setWhatever("aaa"); //Perfectly valid
如果您没有限制对成员的访问,那么任何人都可以获取该对象并对其进行修改
例如:yourClass.getObject().setWhatever(“aaa”)。
防御性复制意味着
getObject()
不会直接返回该对象,但它会复制该对象,然后返回该对象。这样,如果调用方修改了返回的对象,它就不会修改类的原始成员。第5点建议,任何时候如果有任何方法返回与可变对象有关的内容,您都希望创建一个独立于私有状态的副本。例如:
final Object obj = new Object();
obj = new Object(); //Invalid
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);
}
}
公共最终课程Foo
{
私有最终列表字符串;
公共Foo(列表字符串)
{
//防御性建筑复制。防止建筑
//修改列表的代码。
this.strings=新的ArrayList(字符串);
}
公共列表getStrings()
{
//防御性读取拷贝。防止客户端更改列表。
返回新的ArrayList(字符串);
}
}
注意,只有当状态是可变的时,才需要防御性复制。例如,如果在上述类中使用ImmutableList
(例如来自Guava)作为状态,则需要在构造时创建一个新列表(除非输入也是ImmutableList
),而不是在getStrings
中
还要注意,在这种情况下,
String
是不可变的,因此我们不需要复制每个字符串。如果这是一个列表
,我们需要创建一个新列表和每个元素的一个新副本,作为防御副本的一部分。正如你所看到的,当你所有的状态都是不变的时,生活就会变得简单。我在搜索这个话题时偶然发现了这个答案。当列表中的X对象不受我们控制,并且是可变的,并且不提供可靠的克隆方法时,该怎么办?@Jitendra:这取决于上下文。也许您正处于这样一种情况,您可以相信其他代码不会更改值。。。或者,您可能需要自己有效地克隆这些值。这里没有唯一正确的答案。