什么是发布对象——使对象在当前作用域之外的代码中使用
什么是逸出——当某个不应该发布的对象被发布时
对象如何逸出的
- 最简单的方法是将对象的引用保存到一个公有的静态变量中
- 当发布某个对象时,可能会间接地发布其他对象。如果将一个对象添加到被发布的集合对象中,那么同样会发布这个对象
- 当发布一个对象时,在该对象的非私有域中引用的所有对象同样会被发布;或者说当把一个对象传递给某个外部方法时,就相当于发布了这个对象
- 不安全的对象构造过程:指this引用在构造函数中逸出
- 常见的错误做法1是,在构造函数中启动一个线程,this引用就被新创建的线程共享了
- 常见的错误做法2是,在构造函数中注册一个事件监听器,this引用就被触发被监听事件的线程共享了
- 解决办法是:使用一个私有的构造函数和一个公共的工厂方法,看下面的例子
public class SafeListener { private final EventListener listener; private SafeListener() { listener = new EventListener() { public void onEvent(Event e) { doSomething(e); } }; } public static SafeListener newInstance(EventSource source) { //只有当构造函数返回时,this引用才应该从线程中逸出 SafeListener safe = new SafeListener(); source.registerListener(safe.listener); return safe; } }
注意:只有当对象的构造函数返回时,对象才处于可预测和一致的状态。因此,当从对象的构造函数中发布对象时,只是发布了一个尚未构造完成的对象,即使发布对象的语句在最后一行也是如此,如果this在构造过程中逸出,那么这种对象就被认为是不正确的构造