我正在阅读Joshua Bloch的“Effective Java”,第39项进行防御性复制,我有一些疑问。我总是使用以下构造:
MyObject.getSomeRef().setSomething(somevalue);
它的缩写为:
SomeRef s = MyClass.getSomeRef();
s.setSomething();
MyObject.setSomeRef(s);
它始终有效,但是我想如果我的
getSomeRef()
返回一个副本,那么我的快捷方式将不起作用,如果可以安全地使用快捷方式,怎么知道MyObject
的实现是否被隐藏了? 最佳答案
您违反了OO编程的两个规则:
请注意,这些规则只是规则,有时甚至可以被打破。
但是,如果某些数据归对象所有,并且该对象应保证其所拥有的对象具有某些不变性,则它不应将其可变的内部数据结构暴露给外部。因此,需要防御性副本。
另一个经常使用的习惯用法是返回可变数据结构的不可修改的 View :
public List<Foo> getFoos() {
return Collections.unmodifiableList(this.foos);
}
例如,如果您必须确保对列表的每次修改都通过该对象,则该惯用语或防御性复制惯用语可能很重要。
public void addFoo(Foo foo) {
this.foos.add(foo);
someListener.fooAsBeenAdded(foo);
}
如果您不进行防御性复制或返回列表的不可修改 View ,则调用者可以将foo直接添加到列表中,并且不会调用侦听器。