Java編程思想筆記五:多態(tài)

這一章節(jié)主要介紹了 Java 語言多態(tài)的概念和特性,具體內(nèi)容如下:

本章概要

1.什么是多態(tài)

我們先看這樣一個例子:有三種樂器 Wind(管樂)弟疆、Brass(銅管樂)和 Stringed(弦樂)都繼承自 Instrument(樂器)

多態(tài).png

基類有一個演奏樂符(Note)的方法 play:

public enum Note {
    MIDDLE_C, C_SHARP, B_FLAT;
}

class Instrument {
    public void play(Note n) {
        print("Instrument.play() " + n);
    }
}

Wind 想演奏屬于自己樂器的音符,它需要實現(xiàn)自己的 play 方法:

class Wind extends Instrument {
    public void play(Note n) {
        print("Wind.play() " + n);
    }
}

我們在演奏時可以這樣調(diào)用:

public class Music {
    public static void tune(Instrument i) {
        i.play(Note.MIDDLE_C);
    }

    public static void main(String[] args) {
        Wind flute = new Wind();
        tune(flute);
    }
}

輸出結(jié)果為:

Wind.play() MIDDLE_C

我們定義的 tune 方法接收一個 Instrument 類型參數(shù),也可以接收導(dǎo)出自 Instrument 的參數(shù)灯谣,同時會根據(jù)參數(shù)類型執(zhí)行對應(yīng)類型提供的方法,這就是多態(tài)蛔琅。

2.多態(tài)是怎么實現(xiàn)的

多態(tài)讓我們省了很多冗余的代碼胎许,但是再深入想想,編譯器是如何根據(jù)入?yún)⒌念愋驼业揭獔?zhí)行的對應(yīng)的方法的呢罗售?像在 C 語言中辜窑,編譯器和連接器會把每個方法調(diào)用同方法主體在程序執(zhí)行前關(guān)聯(lián)起來,這種機(jī)制叫前期綁定寨躁,哪個方法接收哪種類型的參數(shù)在程序運行前就確定了穆碎,不存在根據(jù)入?yún)㈩愋团袛鄨?zhí)行哪個方法的問題,所以 C 語言也就不存在多態(tài)的概念职恳。

Java 的方法調(diào)用和方法主體是在運行時綁定的所禀,調(diào)用機(jī)制會根據(jù)實際的入?yún)㈩愋团袛嗾{(diào)用哪個方法,這種機(jī)制叫后期綁定放钦。Java 中除了 static 方法和 final 方法(private 方法屬于 final 方法)之外北秽,其他所有方法都是后期綁定,所以對方法使用 static 或 final 修飾就是關(guān)閉其動態(tài)綁定機(jī)制最筒。

多態(tài)的特性

  • 特性1:final 方法(包括 private 方法)不具有多態(tài)性

下面我們來看一個典型的例子:

public class PrivateOverride {
    private void f() { print("private f()"); }
    public static void main(String[] args) {
        PrivateOverride po = new Derived();
        po.f();
    }
}

class Derived extends PrivateOverride {
    public void f() { print("public f()"); }
}

輸出結(jié)果:

private f()

你期望的輸出結(jié)果是不是 public f()贺氓?可結(jié)果恰恰相反……因為基類中的 f() 是 private 方法,被自動認(rèn)為是 final 方法床蜘,且對于導(dǎo)出類不可見辙培,因此,Derived 類中的 f() 方法是一個全新獨立的方法邢锯,所以上述案例基類中的對象 po 在方法調(diào)用時不會發(fā)生多態(tài)扬蕊,只會向上轉(zhuǎn)型為基類對象并執(zhí)行基類的 private 方法。

  • 特性2: 靜態(tài)方法不具有多態(tài)性

靜態(tài)方法是與類丹擎,而非與單個對象關(guān)聯(lián)的尾抑。

  • 特性3: 方法有多態(tài)性,域沒有多態(tài)性

下面看一個簡單的例子:

class Super {
    public int field = 0;
    public int getField() { return field; }
}

class Sub extends Super {
    public int field = 1;
    public int getField() { return super.field;}
}

public class FieldAccess {
    public static void main(String[] args) {
        Super sup = new Sub();
        System.out.println("sup.field = " + sup.field + 
            ", sup.getField() = " + sup.getField());
    }
}

輸出結(jié)果:

sup.field = 0, sup.getField() = 1

field 是域不具備多態(tài)性蒂培,只會向上轉(zhuǎn)型為基類 Super再愈,然后獲取 Super.field 的值;getField 是 public 方法护戳,具備多態(tài)性翎冲,會執(zhí)行 Sub.getField() 方法。

3.向下轉(zhuǎn)型

向上轉(zhuǎn)型(在繼承層次中向上移動)會丟失具體的類型信息媳荒,而向下轉(zhuǎn)型(在繼承層次中向下移動)可以獲取具體的類型信息抗悍,但是向下轉(zhuǎn)型并不是安全的驹饺。

如果方法調(diào)用的入?yún)榛悾怯窒朐L問導(dǎo)出類對象的擴(kuò)展接口缴渊,此時可以嘗試向下轉(zhuǎn)型赏壹,但是向下轉(zhuǎn)型并非安全的。在 Java 語言中衔沼,進(jìn)入運行時后會對每一個類型轉(zhuǎn)換(包括普通的加括號形式的類型轉(zhuǎn)換卡儒,也包括向下轉(zhuǎn)型)進(jìn)行檢查,以確保它是我們希望的那種類型俐巴,如果不是就會返回一個 ClassCastExecption 異常,這種行為稱為“運行時類型識別(RTTI)”硬爆。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末欣舵,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子缀磕,更是在濱河造成了極大的恐慌缘圈,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件袜蚕,死亡現(xiàn)場離奇詭異糟把,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)牲剃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門遣疯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人凿傅,你說我怎么就攤上這事缠犀。” “怎么了聪舒?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵辨液,是天一觀的道長。 經(jīng)常有香客問我箱残,道長滔迈,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任被辑,我火速辦了婚禮燎悍,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘盼理。我一直安慰自己间涵,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布榜揖。 她就那樣靜靜地躺著勾哩,像睡著了一般抗蠢。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上思劳,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天迅矛,我揣著相機(jī)與錄音,去河邊找鬼潜叛。 笑死秽褒,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的威兜。 我是一名探鬼主播销斟,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼椒舵!你這毒婦竟也來了蚂踊?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤笔宿,失蹤者是張志新(化名)和其女友劉穎犁钟,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體泼橘,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡涝动,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了炬灭。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片醋粟。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖重归,靈堂內(nèi)的尸體忽然破棺而出昔穴,到底是詐尸還是另有隱情,我是刑警寧澤提前,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布吗货,位于F島的核電站,受9級特大地震影響狈网,放射性物質(zhì)發(fā)生泄漏宙搬。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一拓哺、第九天 我趴在偏房一處隱蔽的房頂上張望勇垛。 院中可真熱鬧,春花似錦士鸥、人聲如沸闲孤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽讼积。三九已至肥照,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間勤众,已是汗流浹背舆绎。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留们颜,地道東北人吕朵。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像窥突,于是被迫代替她去往敵國和親努溃。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容