国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

進一步理解Java中的多態概念

2019-11-26 15:01:11
字體:
來源:轉載
供稿:網友

多態性有兩種:
1)編譯時多態性
對于多個同名方法,如果在編譯時能夠確定執行同名方法中的哪一個,則稱為編譯時多態性.
2)運行時多態性
如果在編譯時不能確定,只能在運行時才能確定執行多個同名方法中的哪一個,則稱為運行時多態性.

方法覆蓋表現出兩種多態性,當對象獲得本類實例時,為編譯時多態性,否則為運行時多態性,例如:
XXXX x1 = new XXXX(參數列表); //對象獲得本類實例,對象與其引用的實例類型一致
XXX xx1 = new XXX(參數列表);
x1.toString(); //編譯時多態性,執行XXX類的方法.
xx1.toString(); //編譯時多態性,執行XXXX類覆蓋的方法.
XXXX為XXX的父類.
由于子類對象既是父類對象,父類對象與子類對象之間具有賦值相容性,父類對象能夠被賦值為子類對象.例如,
XXXX x2 = new XXX(參數列表); //父類對象獲得子類實例,子類對象即是父類對象
x2.toString(); //運行時多態
 
x2聲明為父類對象卻獲得子類XXX的實例,那么x2.toString()究竟執行父類方法還是執行子類覆蓋的方法呢?
這分為兩種情況:
取決于子類是否覆蓋父類方法.如果子類覆蓋父類方法,則執行子類方法;
如果沒有覆蓋,則執行父類方法.
在編譯時,僅僅依據對象所屬的類,系統無法確定到底應該執行那個類的方法,只有運行時才能確定,因此這是運行時多態.
父類對象并不能執行所有的子類方法,只能執行那些父類中聲明/子類覆蓋的子類方法.

java多態實現
java的多態和c++一樣,是通過動態綁定或者說運行時綁定來實現的。當調用某一個對象引用的方法時,因為編譯器并不知道這個引用到底指向的是變量聲明時說明的類型對象,還是該類型子類的對象。因此編譯器無法為這次調用綁定到具體的某個方法。只有通過java中運行時類型識別(RTT)在運行時綁定到具體的方法

方法的重寫overriding和方法的重載overloading是java多態的不同表現。重寫overriding是父類和子類之間多態性的一種表現,重載overloading是一個類中多態性的表現。

給出一個具體例子:

  

 class People {   public String toString() {    return "I am a people!";   }     public void eat() {   };     public void speak() {   };  }    class Boy extends People {   public String toString() {    return "I am a boy!";   }     public void fight() {   };     public void speak() {   };  }    class Girl extends People {   public String toString() {    return "I am a girl!";   }     public void sing() {   };     public void speak() {   };  }    public class TestToString {   public static void main(String args[]) {    People p = new Girl();    System.out.println(p.toString());   }  } 

運行結果是:

I am a girl!

p是People的一個引用,但是在運行時因為是Girl對象,所以還是調用了Girl的toString方法


深入理解java多態
聲明,這里借鑒了其他同學的例子,原文鏈接:http://blog.csdn.net/thinkghoster/article/details/2307001

測試題目

 class A {   public String show(D obj) {    return "A and D";   }      public String show(A obj) {    return "A and A";   }  }    class B extends A {   public String show(B obj) {    return "B and B";   }      public String show(A obj) {    return "B and A";   }  }    class C extends B {     }    class D extends B {     }    public class Main {   public static void main(String args[]) {    A a1 = new A();    A a2 = new B();    B b = new B();    C c = new C();    D d = new D();        System.out.println(a1.show(b)); // 1    System.out.println(a1.show(c)); // 2    System.out.println(a1.show(d)); // 3    System.out.println(a2.show(b)); // 4    System.out.println(a2.show(c)); // 5    System.out.println(a2.show(d)); // 6    System.out.println(b.show(b)); // 7    System.out.println(b.show(c)); // 8    System.out.println(b.show(d)); // 9   }  } 

答案

 A and A  A and A  A and D  B and A  B and A  A and D  B and B  B and B  A and D 

解析
我開始做這道題目,4、5、6、9全部做錯了,原因就是沒能很好的理解java的多態性,這里說明一下

首先,要深刻的理解重寫和重載,重寫不僅僅包括了函數名稱相同,也包括參數類型和返回值類型

其次,深刻理解這句話“當超類對象引用變量引用子類對象時,被引用對象的類型而不是引用變量的類型決定了調用誰的成員方法,但是這個被調用的方法必須是在超類中定義過的,也就是說被子類重寫的方法”

然后,我們在來分析一下這幾道題目

問題:你認為B重寫了父類A的show方法了嗎?如果重寫了,重寫了幾個?

答案:重寫了,重寫了一個,也就是public String show(A obj),為什么public String show(B obj)不算重寫父類方法呢,很簡單,因為參數類型不同

舉例分析
看了上面的分析,我們也來分析兩個例子:

一、a2.show(b):

a2是一個引用變量,類型為A,b是B的一個實例。首先,在類A中找show(B obj),沒有找到。于是到A的超類中找,而A沒有超類,因此轉向了A.this((super)B),(super)B為A,因此在A中找到了show(A obj)的方法,但是由于a2引用的類B的一個對象,B重寫了A的show(A obj)方法,因此最終鎖定到類B的show(A obj),輸出為“B and A”

二、a2.show(c):
a2是一個引用變量,類型為A,b是B的一個實例。首先,在類A中找show(C obj),沒有找到。于是到A的超類中找,而A沒有超類,因此轉向了A.this((super)C),(super)C為B,到這里為止,這個a2.show(c)變成了a2.show(b)的問題,而a2.show(b)上面已經分析了是輸出"B and A",因此這里也是輸出“B and A”


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 乳山市| 曲沃县| 台安县| 延吉市| 临海市| 增城市| 台州市| 图木舒克市| 绩溪县| 基隆市| 玉山县| 塘沽区| 金门县| 师宗县| 祁东县| 贵南县| 太仆寺旗| 南雄市| 高邑县| 育儿| 余庆县| 梁山县| 许昌市| 轮台县| 蓬莱市| 吉隆县| 休宁县| 正宁县| 天镇县| 邵武市| 广德县| 泽库县| 东源县| 郑州市| 永顺县| 建瓯市| 卢氏县| 中方县| 蓬溪县| 泾源县| 东台市|