【JAVA学习路-think in java】p163:在子类对象生成时,基类构造器调用子类同名函数发生的意料之外的事

package pkg;

//main
public class p163 {
	public static void main(String[] args) {
		new Gextend(5);
	}
}

//*
class Gbase{
	Gbase(){
		System.out.println("Gbase() before invoking methods:");
		method_public();//DYNAMIC
		method_protect();//DYNAMIC
		method_default();//DYNAMIC
		method_static();
		method_final();
		method_private();
		System.out.println("Gbase() after invoked methods");		
	}
	public void method_public() {
		System.out.println("Gbase.method_public()");
	}
	protected void method_protect() {
		System.out.println("Gbase.method_protected()");
	}
	void method_default() {
		System.out.println("Gbase.method_default()");
	}
	static void method_static() {
		System.out.println("Gbase.method_static()");
	}
	final void method_final() {
		System.out.println("Gbase.method_final()");
	}
	private void method_private() {//is final function
		System.out.println("Gbase.method_private()");
	}

}
//**
class Gextend extends Gbase{
	private int radius=1;
	static int rad=2;
	
	Gextend(int r){
		radius=r;
		System.out.print("Gextend(),radius="+radius);
	}
	
	public void method_public() {
		System.out.println("Gextend.method_public(),radius="+radius);
	}
	protected void method_protect() {
		System.out.println("Gextend.method_protected(),radius="+radius);
	}
	void method_default() {//will @override Gbase.method_default()
		System.out.println("Gextend.method_default(), radius="+radius);
	}
	static void method_static() {
		System.out.println("Gextend.method_static()"+rad);
		//System.out.println("Gextend.method_static()"+radius);
		//Cannot make a static reference to the non-static field radius	
	}
	//final void method_final() NOT allowed for FINAL
	private void method_private() {//is final function
		System.out.println("Gextend.method_private()"+radius);
	}
	
}

OUTPUT:

Gbase() before invoking methods:
Gextend.method_public(),radius=0
Gextend.method_protected(),radius=0
Gextend.method_default(), radius=0

Gbase.method_static()
Gbase.method_final()
Gbase.method_private()

Gbase() after invoked methods
Gextend(),radius=5

总结:

1、在生产子类对象时,调用基类构造器期间,若调用了子类/基类的同名函数,对于public、protected、default函数(动态绑定),以覆盖方式调用子类同名函数。而对于static、final、private函数,则调用基类原有方法。

2、在子类构造器被调用之前,若调用了子类的方法,则由于在任何事情发生前,对象的分配存储空间初始化为二进制0,方法所涉及的变量应为0。

3、构造器编写准则:用尽可能的方法使得对象进入正常状态,如果可以的话,避免调用其他方法。构造器唯二能安全调用的方方法是基类中的final、private方法,其不能被覆盖。

发布了42 篇原创文章 · 获赞 23 · 访问量 8265

猜你喜欢

转载自blog.csdn.net/Andrew_Zeng/article/details/104204752
今日推荐