有效的Java防御性副本 [英] Defensive copy from Effective Java

查看:98
本文介绍了有效的Java防御性副本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在阅读Joshua Bloch的有效Java,项目39做防御副本,我有一些问题。我总是使用以下结构:

  MyObject.getSomeRef()。setSomething(somevalue); 

哪个是:

  SomeRef s = MyClass.getSomeRef(); 
s.setSomething();
MyObject.setSomeRef(s);

它始终有效,但我猜,如果我的 getSomeRef()正在返回副本,那么我的快捷方式将无法正常工作,如果可以安全使用快捷方式,是否隐藏了 MyObject 的实现是否隐藏?

解决方案

您违反了OO编程的两个规则:




  • 不要和陌生人交谈

  • 封装



请注意,规则只是规则,它们可以甚至必须被打破。



但是如果一些数据是由一个对象拥有的,而该对象应该保证一些对它拥有的对象不变量,那么它不应该将其可变内部数据结构暴露给外部。因此,需要一个防御性副本。



另一个常用的成语是返回可变数据结构的不可修改的视图:

  public List< Foo> getFoos(){
return Collections.unmodifiableList(this.foos);
}

这个成语或防御性复制成语可能很重要,如果您必须确保列表中的每个修改都会通过对象:

  public void addFoo(Foo foo){
this.foos.add(foo);
someListener.fooAsBeenAdded(foo);
}

如果您没有制作防御性副本或返回不可修改的视图列表,调用者可以直接向列表中添加一个foo,并且不会调用监听器。


I am reading "Effective Java" by Joshua Bloch, item 39 make defensive copy, and I have some questions. I always use the following construct:

MyObject.getSomeRef().setSomething(somevalue);

which is short for:

SomeRef s = MyClass.getSomeRef();
s.setSomething();
MyObject.setSomeRef(s);

It always works, but I guess if my getSomeRef() was returning a copy then my shortcut would not work, how can I know if the implementation of MyObject is hidden if it is safe to use a shortcut or not?

解决方案

You're violating two rules of OO programming:

  • do not talk to strangers
  • encapsulation

Note that these rules are just rules, and that they can, or even must be broken sometimes.

But if some data is owned by an object, and the object is supposed to guarantee some invariants on the objects it owns, then it should not expose its mutable internal data structures to the outside. Hence the need for a defensive copy.

Another often used idiom is to return unmodifiable views of the mutable data structures:

public List<Foo> getFoos() {
    return Collections.unmodifiableList(this.foos);
}

This idiom, or the defensive copy idiom, can be important, for example, if you must make sure that every modification to the list goes through the object:

public void addFoo(Foo foo) {
    this.foos.add(foo);
    someListener.fooAsBeenAdded(foo);
}

If you don't make a defensive copy or return an unmodifiable view of the list, a caller could add a foo to the list directly, and the listener would not be called.

这篇关于有效的Java防御性副本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆