我正在阅读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直接添加到列表中,并且不会调用侦听器。

    10-08 04:35