java基礎之【繼承--->多態】內存圖

執行流程

<span style="font-size:14px;">1:Animal a = new Cat();
	1.1:在棧中創建區域,類型爲Animal,變量名:a;
	1.2:在堆中new Cat();佔用一塊區域。地址值:[0x3a4]
	1.3:spuer()實例化父類Animal。
		1.3.1:new Animal();佔用一塊區域,地址值:0x3ab;
		1.3.2:引用着在方法區中初始化[Animal中的所有方法,該引用爲:[0x754]]。
		1.3.3:將Animal()引用賦給spuer();spuer引用着Animal();
	1.4:在方法區中初始化Cat類的所有方法,引用值爲0x343。
	1.5:將0x3a4賦給棧中的變量a;a就開始引用Cat()。
2:a.eat();
	2.1:通過[0x3a4]找到Cat。
	2.2:編譯時期:先spuer()找到Animal中的方法。如果沒有,則報錯。
	2.3:運行時:直接在Cat中找到eat(),當Cat中沒有,再去Animal中找。
	2.4:將eat()方法要方法區壓棧,執行,輸出:SOP(貓吃魚);
3:a = new Dog();
	3.1:在堆new Dog(),開闢一塊新區域,地址值:0x87xfds
	3.2:spuer();實例化父類Animal  
		3.2.1:new Animal()開闢新區域,地址值0x33fa;
		3.2.2:成員方法引用着方法區中已初始化的[0x754];
		3.2.3:將Animal地址值0x33fa賦給spuer();;spuer引用着Animal();
	3.3:在方法區中初始化Dog類的所有方法,引用值爲0x422ac。
	3.4:將[0x87xfds]賦給棧中的變量a;  a不再引用Cat,而是引用着Dog;這時堆中的Cat已成爲垃圾,等待JVM空閒時來回收。
4:a.eat();
	4.1:通過a變量引用值找到堆中標記爲0x87xfds的區域。
	4.2:編譯時:先進super();去檢查Animal引用的方法區中有沒有eat()方法,如有沒有則報錯。
	4.3:運行時:直接去Doa方法區中找到eat();如果Doa沒有,再去執行super()調用父類的eat()方法。
	4.4:從方法區中將eat()壓棧,執行(SOP('狗吃糧'))。
5:a.shudy();
	5.1:通過a變量引用值找到堆中標記爲0x87xfds的區域。
	5.2:編譯時:先進super();去檢查Animal引用的方法區中有沒有shudy()方法,結果Animal中沒有shudy()方法,所以就在編譯時期就報錯。
6:Dog d = (Dog)a;
	6.1:在棧中開闢區域,存儲類型爲Dog,變量名d
	6.2:將a向下轉型,從Animal轉爲Dog來引用Dog;(將a變量賦給d)
	6.3:a和d都指向堆中同一個Dog對象。
7:d.eat();//從Dog方法中壓棧執行eat()方法,然後彈棧;
8:d.shudy();//從Dog方法中壓棧執行shudy()方法,然後彈棧;
9:Cat c = (Cat) a;
	9.1:在棧中開闢一塊區域,存儲類型:Cat,變量名稱:c
	9.2:將a向下轉型,將Anmail引用Dao轉爲Cat引用Dog;結果拋出類型轉換異常。Dog不能被轉爲Cat;</span>



總結:
   1:多態=繼承+重寫+父類引用子類         如: Fu ff = new Zi();
   2:普通成員
            變量:都參考左邊,因爲變量不存在重寫,方法中調用變量採用就近原則。
    方法:編譯參考左邊,運行參考右邊。
   3:靜態成員
          變量和方法:編譯運行都參考左邊;  因爲靜態與對象無關。成員加靜態修飾的沒加private,都可以被類直接調用,所以參考的都是左邊。

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