我正在阅读 Joshua Bloch 的“Effective Java”,第 39 项 make defensive copy,我有一些问题。我总是使用以下结构:
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 添加到列表中,并且不会调用监听器。
关于java - Effective Java 的防御副本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9743513/