日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

如何理解父類引用指向子類對象

 yliu277 2019-07-18

對象的內(nèi)存角度來理解試試.

假設現(xiàn)在有一個父類Father,它里面的變量需要占用1M內(nèi)存.有一個它的子類Son,它里面的變量需要占用0.5M內(nèi)存.

現(xiàn)在通過代碼來看看內(nèi)存的分配情況:

Father f = new Father();//系統(tǒng)將分配1M內(nèi)存.

Son s = new Son();//系統(tǒng)將分配1.5M內(nèi)存!因為子類中有一個隱藏的引用super會指向父類實例,所以在實例化子類之前會先實例化一個父類,也就是說會先執(zhí)行父類的構造函數(shù).由于s中包含了父類的實例,所以s可以調(diào)用父類的方法.

Son s1 = s;//s1指向那1.5M的內(nèi)存.

Father f1 = (Father)s; 相當于Father f1 = new Son(); 為向上類型轉(zhuǎn)換,可省略,因為子類就是父類,如貓就是動物

//這時f1會指向那1.5M內(nèi)存中的1M內(nèi)存,即是說,f1只是指向了s中實例的父類實例對象,所以f1只能調(diào)用父類的方法(存儲在1M內(nèi)存中),而不能調(diào)用子類的方法(存儲在0.5M內(nèi)存中).

Son s2 = (Son)f;  //Error 不可直接向下類型轉(zhuǎn)換

//這句代碼運行時會報ClassCastException.因為f中只有1M內(nèi)存,而子類的引用都必須要有1.5M的內(nèi)存,所以無法轉(zhuǎn)換.

Son s3 = (Son)f1; 強制類型轉(zhuǎn)換,為向下類型轉(zhuǎn)換,前提是父類引用要先指向子類對象

//這句可以通過運行,這時s3指向那1.5M的內(nèi)存.由于f1是由s轉(zhuǎn)換過來的,所以它是有1.5M的內(nèi)存的,只是它指向的只有1M內(nèi)存.

示例:

1 .如果你想實現(xiàn)多態(tài),那么必須有三個條件,父類引用,子類對象,方法覆蓋你這里如果Fathor類有一個show()方法,那么形成方法覆蓋,那么此時就可以這么寫:obj.show(),此刻形成了多態(tài)

2. 沒有方法覆蓋,那你這里只能解釋為父類引用去訪問一個子類的方法,當然,父類引用沒有這么大范圍的權限,當然會報錯 PS:多態(tài)實際上是一種機制,在編譯時刻,會生成一張?zhí)摂M表,來記錄所有覆蓋的方法,沒有被覆蓋的方法是不會記錄到這張表的.若一個父類引用調(diào)用了沒有覆蓋的子類方法,那么是不符合該表的,那么編譯時刻就會報錯在執(zhí)行程序的時候,虛擬機會去這張?zhí)摂M表中找覆蓋的方法,比如引用中實際上存的是一個子類對象引用,那么就會去找子類中的相應的覆蓋的方法來執(zhí)行

  1. class Father{
  2. void print(){};
  3. }
  • 1
  1. class Son extends Father{
  2. void print(){System.out.println('子類中!');}
  3. void show(){System.out.println('show 中!');}
  4. }
  • 1
  1. class Demo{
  2. public static void main(String args[]){
  3. Father obj=new Son();
  4. obj.print();
  5. obj.show(); //這個調(diào)用會報錯!,即指向子類對象的父類引用不能調(diào)用父類有而子類沒有的方法
  6. }
  7. }
  • 1

定義一個父類類型的引用指向一個子類的對象既可以使用子類強大的功能,又可以抽取父類的共性。
所以,父類類型的引用可以調(diào)用父類中定義的所有屬性和方法,而對于子類中定義而父類中沒有的方法,它是無可奈何的;
同時,父類中的一個方法只有在在父類中定義而在子類中沒有重寫的情況下,才可以被父類類型的引用調(diào)用;
看下面這段程序:

    
上面的程序是個很典型的多態(tài)的例子。子類Child繼承了父類Father,并重載了父類的func1()方法,重寫了父類的func2()方法。重載后的func1(int i)func1()不再是同一個方法,由于父類中沒有func1(int i),那么,父類類型的引用child就不能調(diào)用func1(int i)方法。而子類重寫了func2()方法,那么父類類型的引用child在調(diào)用該方法時將會調(diào)用子類中重寫的func2()
那么該程序?qū)蛴〕鍪裁礃拥慕Y(jié)果呢?
很顯然,應該是“CCC”

  1. class Father{
  2. public void func1(){
  3. func2();
  4. }
  5. //這是父類中的func2()方法,因為下面的子類中重寫了該方法
  6. //所以在父類類型的引用中調(diào)用時,這個方法將不再有效
  7. //取而代之的是將調(diào)用子類中重寫的func2()方法
  8. public void func2(){
  9. System.out.println('AAA');
  10. }
  11. }
  12. class Child extends Father{
  13. //func1(int i)是對func1()方法的一個重載
  14. //由于在父類中沒有定義這個方法,所以它不能被父類類型的引用調(diào)用
  15. //所以在下面的main方法中child.func1(68)是不對的
  16. public void func1(int i){
  17. System.out.println('BBB');
  18. }
  19. //func2()重寫了父類Father中的func2()方法
  20. //如果父類類型的引用中調(diào)用了func2()方法,那么必然是子類中重寫的這個方法
  21. public void func2(){
  22. System.out.println('CCC');
  23. }
  24. }
  25. public class PolymorphismTest {
  26. public static void main(String[] args) {
  27. Father child = new Child();
  28. child.func1();//打印結(jié)果將會是什么?
  29. }
  30. }
  • 1

變量是不存在重寫覆蓋的!

  1. public class A { int a = 1; }
  2. public class B extends A { int a = 2; }
  3. 測試類里調(diào)用了這個方法void compare(){
  4. if(super.a == this.a)
  5. System.out.println('not overrided');
  6. else
  7. System.out.println('overrided');}
  8. 控制臺出來的是overrided
  • 1

類中的屬性是沒有多態(tài)性的,即你在引用上面使用屬性時,系統(tǒng)只會去找引用的靜態(tài)類型中的那個屬性,而與它的實際類型無關。
靜態(tài)方法也是沒有多態(tài)性的。

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多