概念
- 发布一个对象(publish):
使对象能够在当前作用域范围之外的代码中使用; - 逸出(escape):
当某个不应该发布的对象被发布出去的情况;
发布对象的两种方法:
- 将对象的引用保存到一个公有的静态变量中,以便于任何类和线程都能够看见该对象;
举例
public class Set<Secret> KnowSecrets;
public void initialize()
{
knownSecrets = new HashSet<Secret>();
}
- 发布一个内部的类实例;
举例
public class ThisEscape
{
public ThisEscape(EventSource source)
{
source.registerListener(
{
new EventListener()
{
public void onEvent(Event e)
{
doSomething(e);
}
}
});
}
}
发布某对象的影响:
- 发布某对象,可能会间接地发布其他对象;
如上述第一个程序中,如果将一个Sectet对象添加到集合knownSecrets中,那么同样会发布这个对象,因为任何代码都可以访问该集合(由于是public,公有的),并获得对这个新Secret对象的引用。 - 发布某对象时,该对象的非私有域中引用的所有对象同样会被发布;
一般来说,如果一个已经发布的对象能够通过非私有的变量引用和方法调用到达其他的对象,那么这些对象也都会被发布。
外部方法(Alien Method):
假设一个类A,则行为并不完全由类A来规定的方法,包括其他类中的定义的方法以及类A中可以被改写的方法(既不是private方法也不是final方法),则这些方法就称作为外部方法。
安全的构造函数过程
- 不要再构造过程中使用this引用逸出,那何时使用this引用逸出?
只有当构造函数返回时,this引用才应该从线程中逸出,构造函数可将this引用保存到某地方,只要其他线程在构造函数完成前不使用它即可。 - this应用逸出的错误操作
在构造函数中启动一个线程。(在构造函数中创建线程并没有错误,但是最好不要立即启动它,而是通过start或者initialize方法来启动); - 如何在构造函数中注册一个事件监听器或者启动线程?
使用一个私有的构造函数和一个公共的工厂方法。
举例:使用工厂方法来防止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) {
SafeListener safe = new SafeListener();
source.registerListener(safe.listener);
return safe;
}
}
[source:Java并发编程实战]