使用工厂方法来防止this引用在构造过程中逸出
发布一个对象是使对象能够在当前作用域之外的代码中使用。在许多情况中,我们要确保对象及其内部状态不被发布。在某些情况下,我们又需要发布某个对象,但如果再发布是要确保线程安全性,则可能需要同步。发布内部状态可能会破坏封装性,并使得程序难以维持不变性条件。如果在对象构造完成之前就发布该对象,就会破坏线程安全性。当某个不应该发布的对象被发布时,这种情况就被称为逸出。
例一:发布对象的最简单方法是将对象的引用保存到一个公有的静态变量中,以便任何类和线程都能看见该对象。
public static Set<Secret > knowSecrets;
public void initialize(){
knownSecrets = new HashSet<Secret>();
}
例二:隐式地使用this引用逸出
public class ThisEscape {
public ThisEscape(EventSource source) {
source.registerListener (
new EventListener() {
public void on Event(Event e) {
doSomething(e);
}
});
}
}
发布对象或者其内部状态的机制就是发布一个内部的类实例。当ThisEscape发布EvenListener时,也隐含地发布了ThisEscape实例本身,因为在这个内部类的实例中包含了对ThisEscape实例的隐含引用。
安全的对象 构造过程
不要在构造过程中使this引用逸出。
如果想在构造函数中注册一份事件监听器或启动线程,那么可以使用一个私有的构造函数和和一个公共的工厂方法来防止this引用在构造过程中逸出。
import java.awt.Event;
import java.util.EventListener;
public class SateListener {
private final EventListener listener;
private SateListener() {
listener = new EventListener(){
public void onEvent(Event e) {
doSomething(e);
}
};
}
public static SafeListener newInstance(EventSource source) {
SafeListener safe = new SafeListener();
source.registerListener(safe.listener);
return safe;
}
}