Java異常系列第三集——多態(tài)中的異常

本博客為個人原創(chuàng)以现,轉載需在明顯位置注明出處

多態(tài)在實際項目開發(fā)中是經常用到的一個概念约啊,那么多態(tài)中的異常是怎樣的呢佣赖?下面我們就來討論一下,為了節(jié)省時間憎蛤,我直接用了《Thinking in Java》中的栗子(由于是多態(tài),肯定有一系列的繼承關系萎胰,所以代碼較多技竟,請仔細閱讀):

class BaseballException extends Exception {
}

class Foul extends BaseballException {
}

class Strike extends BaseballException {
}

首先是三個自定義異常類榔组,Foul和Strike均是BaseballException的子類

abstract class Inning {

    public Inning() throws BaseballException {
    }
    
    public Inning(String s) {
    }

    public void event() throws BaseballException {
    }

    public void walk() {
    }

    public abstract void atBat() throws Strike, Foul;

}

接下來是一個抽象類瓷患,其中atBat()是抽象方法遣妥,注意每個方法拋出的異常爱态,下面會有逐個總結和解釋

class StormException extends Exception {
}

class RainedOut extends StormException {
}

class PopFoul extends Foul {
}

又是三個自定義異常锦担,注意洞渔,RainedOut是剛剛定義的StormException的子類缚态,PopFoul是上面定義的Foul的子類

interface Storm {
    public void event() throws RainedOut;

    public void rainHard() throws RainedOut;
}

擦玫芦,還有一個接口桥帆,感覺整個人都不好了,在堅持一下茫多,馬上就到最后了地梨。注意一下宝剖,接口里面有一個event()方法万细,上面抽象類Inning也有一個event()方法赖钞,只是拋出的異常不同

class StormyInning extends Inning implements Storm {

    public StormyInning() throws RainedOut, BaseballException {
        // 構造方法必須throws父類構造方法的Exception
        // 子類構造方法調用super雪营,不可捕獲父類的異常
    }

    public StormyInning(String s) {
        super("");
    }

    @Override
    public void event() {
        // 父類event方法和接口event方法拋出的異常不一致,所以只能重寫方法谴餐,不拋出任何異常
    }

    @Override
    public void rainHard() {
        // 子類重寫方法岂嗓,可以將拋出的異常范圍縮小或者不拋出異常
    }

    @Override
    public void atBat() throws PopFoul {
        // 子類重寫方法厌殉,可以拋出父類拋出異常的子類異常
        // PopFoul extends Foul
    }

    // @Override
    // public void walk() throws StormException {
        // 如果父類方法未拋出異常年枕,子類重寫方法不可拋出異常
    // }
}

終于結束了,最后一個實現類StormInning摩桶,集成抽象類Inning硝清,實現接口Storm芦拿,內部重寫了一些方法蔗崎,下面我們就挨個總結:

重寫方法###

1.父類方法不throws異常缓苛,子類重寫方法不可throws

看代碼中的walk方法未桥,父類Inning中walk方法是沒有拋出異常的冬耿,但是在子類StormInning中重寫并且添加異常說明,編譯不通過的染乌『杀铮回顧一下多態(tài)的概念勒庄,簡單來說就是父類引用指向子類對象,試想一下局装,父類方法中沒有拋出異常铐尚,子類卻拋出了異常宣增,假設可以編譯通過帖旨,那么父類的引用去調用這個方法時解阅,是不需要捕獲異常的,但是真正執(zhí)行的是子類中重寫的方法碉熄,只要子類方法中出現問題拋出異常锈津,結果都是致命的

2.子類重寫方法可以縮小異常范圍或不throws異常

這一點跟1恰恰相反,看rainedOut方法茎杂,在接口中添加了異常說明,但是重寫時去掉了異常說明刽脖。這個是可行的,因為無論怎樣院水,父類引用在調用rainedOut方法時都會提示要捕獲異常衙耕,子類重寫方法中不拋異常沒問題,拋了異常也可以捕獲到厅瞎。

3.子類重寫方法可throws父類異常的子類

看下代碼中的atBat方法,父類Inning中定義拋出的是Foul異常,子類重寫時拋出了Foul的子類PopFoul異常爽柒,這個也是ok的。關于這點可以參考上一篇文章中的異常匹配部分心墅,捕獲異常的時候,父類異常是可以匹配子類異常的铐姚。

4.父類和接口包含同一方法,但定義拋出的異常不同,子類只能重寫方法并且不可throws任何異常

Inning類和Storm接口都有一個相同的event方法悍手,區(qū)別只是拋出的異常類型不同竣付,一個拋出BaseballException異常,另一個是RainedOut異常逸绎,我們在子類StormInning中重寫該方法時朗儒,若只拋出BaseballException醉锄,那么不匹配接口中的定義纲爸,若只拋出RainedOut,就不匹配父類中的定義,兩個異常都拋出冕茅,父類和接口都不匹配,真是里外都不是人。所以這種情況下徒溪,重寫方法時不能拋出任何異常腺阳,正好符合上述總結2腰耙。

構造方法###

1.子類構造方法可以擴大異常范圍

與重寫方法只能縮小異常范圍相反,子類構造方法是可以擴大異常范圍的,為什么运挫?《Thinking in java》中只有結論沒有做任何解釋,說說我的理解:還是多態(tài)的概念碾牌,父類引用在指向具體的對象時,需要new出具體的類對象择膝,子類對象和父類對象是不一樣的誓琼,而在調用方法時父類與子類就沒有區(qū)分,方法名都是一致的肴捉,只是在運行時執(zhí)行的地方不一樣腹侣。那么子類構造方法中擴大異常范圍,增加一些其他異常的拋出齿穗,完全不會影響調用方的異常捕獲傲隶。可以參考代碼中StormInning類的無參構造方法缤灵,比父類多拋出了RainedOut異常

2.如果子類構造方法調用了父類的有異常拋出的構造方法伦籍,必須throws父類構造方法的異常蓝晒,該異常不可再子類中捕獲

還是StormInning的無參構造方法,若是刪除BaseballException的異常說明帖鸦,編譯器就會報錯芝薇,為什么?因為雖然沒有顯示調用作儿,但是StormInning的無參構造方法實際上調用了父類的默認構造方法洛二,而父類Inning的默認構造方法有異常拋出,所以子類必須拋出這個異常攻锰×浪唬或許你會說,我完全可以在子類構造方法中調用一下super()娶吞,然后try-catch垒迂,這樣子類就不需要拋出異常了。一開始我也以為可以妒蛇,實際上卻不行机断,因為我們是無法在子類捕獲父類構造方法拋出的異常的,必須拋出绣夺,至于為什么吏奸,我也不是太清楚,有知道的盆友還請不吝賜教陶耍。

3.父類引用和子類引用在調用方法時奋蔚,捕獲的異常可能不同

這有個前提條件就是父類方法和子類方法拋出的異常要不同才行烈钞,就拿atBat方法為例:

@Test
public void testPolymophism() {
    try {
        StormyInning sinn = new StormyInning();
        sinn.atBat();
    } catch (PopFoul e) {
        e.printStackTrace();
    } catch (RainedOut e) {
        e.printStackTrace();
    } catch (BaseballException e) {
        e.printStackTrace();
    }

    try {
        Inning inn = new StormyInning();
        inn.atBat();
    } catch (Strike e) {
        e.printStackTrace();
    } catch (Foul e) {
        e.printStackTrace();
    } catch (RainedOut e) {
        e.printStackTrace();
    } catch (BaseballException e) {
        e.printStackTrace();
    }       
}

首先構造方法拋出的異常是一致的泊碑,atBat在子類重寫時修改了拋出異常的類型為Foul的子類,所以子類引用在調用時棵磷,只需要捕獲PopFoul異常即可蛾狗;而父類引用在調用時就必須捕獲父類方法定義的兩個Strike和Foul異常。

好了仪媒,關于異常的基本技術細節(jié)就介紹到這里沉桌,很少寫這種純理論的東西,看著讓人昏昏欲睡算吩,但是語言基礎就是這么枯燥留凭,想成為一名優(yōu)秀的程序員,你必須克服偎巢!

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末蔼夜,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子压昼,更是在濱河造成了極大的恐慌求冷,老刑警劉巖瘤运,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異匠题,居然都是意外死亡拯坟,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進店門韭山,熙熙樓的掌柜王于貴愁眉苦臉地迎上來郁季,“玉大人,你說我怎么就攤上這事钱磅∶瘟眩” “怎么了?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵盖淡,是天一觀的道長年柠。 經常有香客問我,道長褪迟,這世上最難降的妖魔是什么彪杉? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮牵咙,結果婚禮上,老公的妹妹穿的比我還像新娘攀唯。我一直安慰自己洁桌,他們只是感情好,可當我...
    茶點故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布侯嘀。 她就那樣靜靜地躺著另凌,像睡著了一般。 火紅的嫁衣襯著肌膚如雪戒幔。 梳的紋絲不亂的頭發(fā)上吠谢,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天,我揣著相機與錄音诗茎,去河邊找鬼工坊。 笑死,一個胖子當著我的面吹牛敢订,可吹牛的內容都是我干的王污。 我是一名探鬼主播,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼楚午,長吁一口氣:“原來是場噩夢啊……” “哼昭齐!你這毒婦竟也來了?” 一聲冷哼從身側響起矾柜,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤阱驾,失蹤者是張志新(化名)和其女友劉穎就谜,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體里覆,經...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡丧荐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了租谈。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片篮奄。...
    茶點故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖割去,靈堂內的尸體忽然破棺而出窟却,到底是詐尸還是另有隱情,我是刑警寧澤呻逆,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布夸赫,位于F島的核電站,受9級特大地震影響咖城,放射性物質發(fā)生泄漏茬腿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一宜雀、第九天 我趴在偏房一處隱蔽的房頂上張望切平。 院中可真熱鬧,春花似錦辐董、人聲如沸悴品。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽苔严。三九已至,卻和暖如春孤澎,著一層夾襖步出監(jiān)牢的瞬間届氢,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工覆旭, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留退子,地道東北人。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓型将,卻偏偏與公主長得像絮供,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子茶敏,可洞房花燭夜當晚...
    茶點故事閱讀 45,092評論 2 355

推薦閱讀更多精彩內容

  • 1. Java基礎部分 基礎部分的順序:基本語法壤靶,類相關的語法,內部類的語法惊搏,繼承相關的語法贮乳,異常的語法忧换,線程的語...
    子非魚_t_閱讀 31,645評論 18 399
  • (一)Java部分 1、列舉出JAVA中6個比較常用的包【天威誠信面試題】 【參考答案】 java.lang;ja...
    獨云閱讀 7,111評論 0 62
  • 兩類異常 Java中的異常繼承體系為: 這里的異常( Exception)分為兩大類:Checked異常和Runt...
    tobe_superman閱讀 639評論 0 0
  • 對象的創(chuàng)建與銷毀 Item 1: 使用static工廠方法向拆,而不是構造函數創(chuàng)建對象:僅僅是創(chuàng)建對象的方法亚茬,并非Fa...
    孫小磊閱讀 1,986評論 0 3
  • “我錯啦”! 她跪在地上聲嘶力竭的說浓恳,準確點應該是喊刹缝。我牙根沒看到丁點的歉意,更多的是在逼迫下的無奈...
    老魁_河北閱讀 355評論 3 1