`

遵循“安全构造”技术

阅读更多

在编写代码的时候,我们应该遵循“安全构造”技术,即在构造函数里面,不将this暴露给其它类。将this暴露出去有什么危险呢?接下来让我们来看一下,两种情况。

1. 显示的this暴露

public class FatherClass {
	FatherClass(){
		Listen listen = new Listen();
                //在父类中将this暴露给了listen
		listen.setFatherClass(this);
	}
	
	public void sayHello(){
		System.out.println("Hello World!");
	}
}

public class SubClass extends FatherClass {
	private String name = null;

	SubClass() {
		super();
		name = "frank";
	}
        //因为name对象还没有被初始化,因此name还是null
	public void sayHello() {
		System.out.println("Hello World " + name + "!");
	}
        //输出Hello World null!
	public static void main(String[] args) {
		SubClass s = new SubClass();
	}
}

public class Listen {
	public void setFatherClass(FatherClass f){
                //调用sayhello方法,因为子类重写了父类的sayhello方法
                //调用子类的sayhello方法
		f.sayHello();
	}
}

 2.隐士的this暴露

public class FatherClass {
	private String name = null;
	FatherClass() {
		Listen listen = new Listen();
                生成匿名内部类,并且把内部类的this暴露给listen
		listen.setInnerClass(new InnerClass() {
			public void sayHello() {
				sayHelloToMe();
			}
		});
		name = "frank";
	}
	//name没有被初始化,输出null
	public void sayHelloToMe() {
		System.out.println("Hello World " + name + "!");
	}
	
	public static void main(String[] args) {
		FatherClass f= new FatherClass();
	}
}

public class Listen {
        //调用innerclass的sayHello方法
	public void setInnerClass(InnerClass f){
		f.sayHello();
	}
}

public class InnerClass{
       //子类重写了sayhello方法,调用子类的sayhello方法
	public void sayHello() {
		System.out.println("Hello World!");
	}
}

 总结:对其它线程能够看见的还未完成构造的对象进行引用显然不是我们所期望的。归根结底,我们如何 正确辨别完全构造好的对象和尚未构造好的对象呢?但通过公布来自构造函数内的 this 引用 ― 直接或间接地通过内部类 ― 我们这样做时,会导致无法预料的后果。为了防止这种危险,在 创建内部类的实例或从构造函数启动线程时,尽量避免使用 this 。如果 无法在构造函数中避免直接或间接使用 this ,则确保不让其它线程看见 this 引用。

参考资料http://www.ibm.com/developerworks/cn/java/j-jtp0618/index.html#ibm-pcon

分享到:
评论
Global site tag (gtag.js) - Google Analytics