要创建一个不可变类,Effective Java有一个最后的条件。
要使类不可变,请遵循以下五条规则:
5-确保对任何可变组件的独占访问。如果您的类具有引用可变对象的任何字段,请确保该类的客户端无法获取对这些对象的引用。永远不要将这样的字段初始化为客户端提供的对象引用,也不要从访问者返回对象引用。在构造函数,访问器和
中制作防御性副本(第24项)readObject
方法
public final class ImmutableClass {
private MutableObject mutableObject;
// If I should not provide getter for this object. Then what is the use of this variable after I have
//initalised in the constructor
}
有人能解释一下这一点吗?
答案 0 :(得分:3)
实际上相当简单。
基本上,它不是说...
因此,如果您的Class
包含java.util.List
作为其中一个字段,则任何使用您的Class
的客户都无法直接获取List
的引用}字段,通过public
减速或某种吸气。
例如......
public class BadImmutableExample {
public List<String> myStrings; // This can not be referenced by the client
/*...*/
}
会很糟糕,因为任何机构都可以访问字段myStrings
来修改...
如果您必须返回List
中的值,您将需要返回List
的副本(不是对它的引用)或返回值的数组,例如。
例如......
public class BadImmutableExample {
private List<String> myStrings; // This can not be referenced by the client
/*...*/
public List<String> getMyStrings() {
return myStrings;
}
}
将List
myStrings
公开给任何客户,这将允许他们修改它。
在这种情况下,您还可以使用Collections.unmodifiableList(myStrings)
使列表无法修改,或者使用return new ArrayList<String>(myStrings)
或返回String
数组...
基本上这意味着如果您的Class
要求客户端使用某种值或值来播种它,则不应该直接维护它们,而是再次为您自己的引用制作副本。
例如......
public class BadImmutableExample {
private List<String> myStrings; // This can not be referenced by the client
public ImmutableExample(List<String> clientStrings) {
myStrings = clientStrings;
}
}
会破坏此规则,因为对clientStrings
的任何更改都会立即反映在您的课程中。
相反,你可以做点像......
public class BetterImmutableExample {
private List<String> myStrings; // This can not be referenced by the client
public ImmutableExample(List<String> clientStrings) {
myStrings = new ArrayList<String>(clientStrings);
}
}
相反,它将复制客户提供的列表,但不再反映对其所做的更改(客户提供的列表)