欢迎来到知了汇智!
联系电话:知了汇智-电话号码 028-62016472 / 13228113191

Java并发编程实践-this溢出的解决办法-知了汇智

Java并发编程实践-this溢出的解决办法

  《Java并发编程实践》一书中,提到“在构造函数中调用一个可覆盖的(那些既不是private,也不是final的)实例方法同样会导致this引用在构造期间溢出。”,这句话读来简单,但是却干货满满,这里举一个简单的示例来进行说明。
  ThisEscape类:
 

public class ThisEscape {	
	public ThisEscape() {
		System.out.println("MyTest");
		// 在构造方法中其调用了非final和private的方法
		Say();
	}

	public void Say() {
		System.out.println("MyTest.Say()");
	}

	public static void main(String[] args) {
		new ThisEscapeSon();
		new ThisEscapeSon("Hello World");
	}
}

Java并发编程实践-this溢出的解决办法

 
  ThisEscapeSon.class类
  ThisEscapeSon继承自ThisEscape类并且重写了Say方法。
 

class ThisEscapeSon extends ThisEscape {
	private final String name;

	public ThisEscapeSon() {
		this.name = "Hello Word";
		System.out.println("MyTest2");
	}

	public ThisEscapeSon(String name) {
		this.name = name;
		System.out.println("MyTest2");
	}

	/*
	 * 在子类中重写Say方法
	 */
	@Override
	public void Say() {
		System.out.println("MyTest2.Say()-->" + name);
	}
}


 
  执行结果
 

MyTest
MyTest2.Say()-->null
MyTest2
MyTest
MyTest2.Say()-->null
MyTest2


 
  分析:无论是调用子类(ThisEscapeSon)的默认构造函数还是带参构造器来实例化ThisEscapeSon实例,默认情况下它都会首先依次调用父类的无参构造方法(相当于构造函数第一行代码处调用父类的无参构造器)实例化父类,接着才会执行子类构造器的其他方法。
  所以,当执行到父类ThisEscape构造器中执行Say()方法时,此时由于子类已经重写了Say()方法,他就会调用子类的Say()方法,实际上,在这里就可以预见this溢出的后果了,由于子类中的this.name语句还没有执行,所以,执行Say()方法时name成员变量并没有被赋值,所以会打印null值。
  总结:父类构造方法调用的非final、private方法,如果存在子类的情况下,对于该方法的执行就会具有不可预见性的问题,这在编程过程需要极度注意的。
 
  修改方式:
  1)将ThisEscape的Say()方法改成private作用域,那么,子类ThisEscapeSon就不能重写该方法,而只是重新定义了Say()方法,此时,只会调用ThisEscape的Say()方法完成相应的功能。
  2)将ThisEscape的Say()方法改成final作用域,那么,如果子类定义Say(),就会报编译器错误,从而防止类似不可以预见性事件的发生。
 
  版权声明:本文来源于网络,由知了堂搜集整理,仅供大家学习Java编程时使用

132 2811 3191
预约免费试学
点击咨询
预约试学