发布一个对象的意思是使它能够被当前范围之外的代码所使用。比如将一个引用存储到其他代码可以访问的地方,在一个非私有的方法中返回这个引用,也可以把它传递到其他类的方法中。在很多情况下,我们需要确保对象及它
们的内部状态不被暴露。一个对象在尚未准备好时就将它发布,这种情况称作逸出。
1. 发布最简单的就是将对象设置到公共静态域中
下面一个发布的代码
public static Set<Secret> knownSecret;
public void initialize(){
knownSecret = new HashSet<Secret>();
}
2.发布第二种简单的方式就是在一个公共方法内直接return 对象的引用
一个数据逸出的例子(不要这样做)
class UnsafeStates{
private String[] states = new String[]{"CHINA","AMERICAN"};
public String[] getStates(){ return states; }
}
以这种方式发布states会出现问题。任何一个调用者可以对数据进行修改,本应该是私有的数据变成了公有的了。
3.第三种的发布就很隐秘了.就是讲自身的对象引用发布到另一个对象的引用中.
可能在构造中出现如此这就是this例如:
public class Test {
private boolean isIt;
public Test() throws InterruptedException {
new Thread(new Runnable() {
public void run() {
System.out.println(isIt);
}
}).start();
Thread.sleep(2000L);
isIt = true;
}
public static void main(String[] args) throws InterruptedException {
Test test = new Test();
}
}
打印的结果是false,这个例子就是隐式的this对象引用逸出,还没有实例化完成时,其他线程就已经要用到对象中的属性
参考了stackoverflow上的文章,理解了什么是构造过程中this引用逸出。
http://stackoverflow.com/questions/1588420/how-does-this-escape-the-constructor-in-java
安全构建的实践
1.不要让this引用在构造期间逸出。
使用工厂方法防止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.register(safe.listener);
return safe;
}
}