關於繼承時子類重寫父類方法和覆蓋父類變量的若干問題 (待進一步研究)


假設,子類重載父類的方法,並將子類的成員覆蓋。

創建子類對象實例,將其上轉型成父類。




例子1

public class Parent {

	public void init() {
		System.out.println("1 init parent");
		this.demo();
	}
	
	public void demo() {
		System.out.println("2 demo parent");
	}

}

public class Son extends Parent {
	
	public void init(){
		super.init();
		System.out.println("3 init son");
		this.demo();
	}
	
	public void demo() {
		System.out.println("4 demo Son");
	}
	
	public static void main(String[] args) {
		//Parent p = new Son();//1
		Son son = new Son();//2
		son.init();  //  init(son)
		
	}

}


當執行1時結果爲:

1 init parent
4 demo Son
3 init son
4 demo Son

當執行2時結果爲:

1 init parent
4 demo Son
3 init son
4 demo Son

情況1和情況2其實是相似的,由於使用new Son()創建實例,上轉型之後,訪問的也是子類重載的方法而Parent中的init()方法中的this也被認爲是指向堆區域中son的實例化對象,故this.demo()訪問的仍然是子類中重載的方法。


例子2

public class Parent {
	
	public String name="tom";

	public void init() {
		System.out.println(this.name);
	}
	
}

public class Son extends Parent {
	
	public String name="jack";
	
	public void init(){
		super.init();
		System.out.println(this.name);
	}
	
	public static void main(String[] args) {
		//1  當前運行類 Son   
		Son son = new Son();
   		son.init();  //init(son)
		System.out.println("## " + son.name);
		
		//2  當前運行類Parent  
		Parent p = new Son();
		p.init();
		System.out.println("** " + p.name);
		
	}

}

當代碼運行1時  我猜測結果應該是:

jack

jack

##jack

但實際結果卻是:

tom
jack
## jack

此時Parent類中this.name指向的是父類中的name值


由於我們無法看到內存中的實際情況,但通過debug我們可以看到son對象中有兩個同名的name變量



只有幾種情況可以解釋這種結果

1.this並不指向son在堆中創建的實例

2.創建對象時內存中使用了其他機制來保證這種結果的生成。


翻看了一下《深入理解Java虛擬機 JVM高級特性與最佳實踐》這本書 似乎得出了一些端倪

由此可見當訪問成員變量時,檢測到父類的成員變量之後程序停止繼續尋找。

對於方法,由於其內容存放在方法區內,每個對象的發放應該是通過其自身的this即引用唯一綁定。故就差不多解釋的通了。

《深入理解Java虛擬機 JVM高級特性與最佳實踐》一書的下載地址:

http://www.jb51.net/books/163531.html#down


上面只是個人的一點點猜測 ,不吝賜教。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章