只想把基礎打好之-異常

在這里說說一些容易忽略的知識點。

  1. 對異常來說最重要的就是異常的類名眼五。要做到見名知義。比如NullPointerException,IllegalStateException等,它們都只是簡單地繼承了RuntimeException。
public class NullPointerException extends RuntimeException {
    private static final long serialVersionUID = 5162710183389028792L;

    /**
     * Constructs a {@code NullPointerException} with no detail message.
     */
    public NullPointerException() {
        super();
    }

    /**
     * Constructs a {@code NullPointerException} with the specified
     * detail message.
     *
     * @param   s   the detail message.
     */
    public NullPointerException(String s) {
        super(s);
    }
}
  1. printStackTrace()方法所提供人信息可以通過getStackTrace()方法來直接訪問,這個方法將返回一個棧軌跡中的元素所構成的數組范舀,其中每一個元素都表示棧中的一幀速那。
public class WhoCalled {
    static void f(){
        try {
            throw new Exception();
        }catch (Exception e){
                  for(StackTraceElement ste:e.getStackTrace()){
                      System.out.println(ste.getMethodName());
                  }
        }
    }
    static void g(){f();}
    static void h(){g();}
    public static void main(String[] args){
        f();
        System.out.println("#############################");
        g();
        System.out.println("#############################");
        h();
        System.out.println("#############################");
    }
}

運行結果:

f
main
invoke0
invoke
invoke
invoke
main
#############################
f
g
main
invoke0
invoke
invoke
invoke
main
#############################
f
g
h
main
invoke0
invoke
invoke
invoke
main
#############################
  1. fillInStackTrack()用來更新棧信息,fillInStackTrack()方法將返回一個Throwable對象尿背。通過下面的例子會直觀一些。
public class Rethrowing {
    public static void f() throws Exception{
        System.out.println("f方法里的原始異常");
        throw new Exception("從f方法里面拋出的異常");
    }
    public static void g() throws Exception{
        try {
            f();
        } catch (Exception e) {
            System.out.println("g方法里面的catch代碼塊");
            e.printStackTrace(System.out);
            throw e;
        }
    }
    public static void h()throws Exception{
        try {
            f();
        } catch (Exception e) {
            System.out.println("h方法里面的代碼塊");
            e.printStackTrace(System.out);
            throw (Exception) e.fillInStackTrace();
        }
    }
    public static void main(String[] args){
        try {
            g();
        } catch (Exception e) {
            System.out.println("main方法中調用g方法");
            e.printStackTrace(System.out);
        }
        System.out.println("#####################");
        try {
            h();
        } catch (Exception e) {
            System.out.println("main方法中調用h方法");
            e.printStackTrace(System.out);
        }

    }
}

運行結果:

f方法里的原始異常
g方法里面的catch代碼塊
java.lang.Exception: 從f方法里面拋出的異常
    at exception.Rethrowing.f(Rethrowing.java:9)
    at exception.Rethrowing.g(Rethrowing.java:13)
    at exception.Rethrowing.main(Rethrowing.java:31)
main方法中調用g方法
java.lang.Exception: 從f方法里面拋出的異常
    at exception.Rethrowing.f(Rethrowing.java:9)
    at exception.Rethrowing.g(Rethrowing.java:13)
    at exception.Rethrowing.main(Rethrowing.java:31)
#####################
f方法里的原始異常
h方法里面的代碼塊
java.lang.Exception: 從f方法里面拋出的異常
    at exception.Rethrowing.f(Rethrowing.java:9)
    at exception.Rethrowing.h(Rethrowing.java:22)
    at exception.Rethrowing.main(Rethrowing.java:38)
main方法中調用h方法
java.lang.Exception: 從f方法里面拋出的異常
    at exception.Rethrowing.h(Rethrowing.java:26)
    at exception.Rethrowing.main(Rethrowing.java:38)

4.異常鏈,Throwable的子類在構造器中都可以一個cause對象作為參數捶惜。這個cause就用來表示原始異常田藐,這樣通過把原始異常傳遞給新的異常,使得在當前位置創(chuàng)建并拋出新的異常吱七,也能通過這個異常鏈追蹤最初發(fā)生的位置汽久。需要注意的是,在Throwabe的子類中踊餐,只有三種基本的異常類提供了帶cause參數構造器它們是Error景醇,Exception和RuntimeException。如果要把其它類型的異常鏈接起來吝岭,應該使用initCause()方法而不是構造器三痰。比如說:

new RuntimeException的子類(RuntimeException的其它子類的對象);
Exception的子類的對象.initCause(RuntimeException的子類對象);

5.在try塊里有return吧寺,finally是會執(zhí)行的。那如果finally也有return呢散劫,會返回哪個呢稚机?

public class FinallyTest {
    public static void main(String[] args){
System.out.println(testFinally());
    }
    private static String testFinally(){
        try{
            return "try";
        }finally {
            return "finally";
        }
    }
}

運行結果:

finally

這種結構會導致代碼可讀性變差。
5.異常的不足就是會導致異常丟失获搏。異常作為程序出錯的標志決不應該被忽略赖条。然而某些使用finally子句就會發(fā)生這種情況。

public class LostException {
    class VeryImportantException extends Exception{
        @Override
        public String toString() {
            return "very important exception";
        }
    }
    class HoHumException extends Exception{
        @Override
        public String toString() {
            return "hohum exception";
        }
    }
    void f() throws VeryImportantException{
        throw new VeryImportantException();
    }
    void dispose() throws HoHumException{
        throw new HoHumException();
    }
    public static void main(String[] args){
        try{
            LostException lost=new LostException();
            try{
                lost.f();
            }finally {
                lost.dispose();
            }
        }catch (Exception e){
            System.out.println(e);
        }
    }
}

運行結果:

hohum exception

從輸出結果中看到VeryImportantException不見了常熙,它被finally子句中的HoHumException取代纬乍。這是相當嚴重的缺陷。
6.異常的限制裸卫,當覆蓋方法的時候仿贬,只能拋出在基類方法的異常說明里列出的那些異常。這些限制很有用彼城,因為這意味著诅蝶,當基類使用的代碼應用到派生類對象的時候握础,一樣能夠工作砌滞,當然這是面向對象的基本概念。異常也不例外哑了。

public class ExceptionTest {
    class BaseException extends Exception{};
    class Foul extends BaseException{};
    class Strike extends BaseException{};
    abstract class Inning{
        public Inning () throws BaseException{}
        public void event () throws BaseException{}
        public abstract void atBat() throws Strike,Foul;
        public void walk(){};
    }
    class StormException extends Exception{};
    class RainedOut extends StormException{};
    class PopFoul extends Foul{};
    interface Storm{
        public void event() throws RainedOut;
        void rainHard() throws RainedOut;
    }
    public class StormyInning extends Inning implements Storm{
        //因為Inning的構造器拋出異常舱馅,所以它的繼承類必須處理父類的異常,當然也可以拋出自己想要處理的異常
        public StormyInning()  throws BaseException,Foul{
        }
        //下面這個方法不能通過編譯缰泡,因為在Inning方法中并沒有拋出異常
//        @Override
//        public void walk() throws PopFoul{
//
//        }
        //接口不能基類中的方法添加異常,所以下面也不能編譯
//        @Override
//        public void event() throws RainedOut{
//
//        }
        @Override
        public void event() {
        }
        //重寫的方法可以拋出繼承的異常
        @Override
        public void atBat() throws PopFoul {
        }
        @Override
        public void rainHard() throws RainedOut {
        }
    }
}

在Inning類中代嗤〖可以看到構造器和event方法都聲明將拋出異常,但實際上并沒有拋出干毅,這種方式使你強制用戶去捕獲可能在覆蓋的event版本中增加的異常宜猜。

7.被檢查異常并不總是好的,它有時候會使問題變得復雜硝逢,因為它強制你在還沒有準備好處理問題的時候加上catch子句姨拥。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市渠鸽,隨后出現的幾起案子叫乌,更是在濱河造成了極大的恐慌,老刑警劉巖徽缚,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件憨奸,死亡現場離奇詭異,居然都是意外死亡凿试,警方通過查閱死者的電腦和手機排宰,發(fā)現死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進店門似芝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人额各,你說我怎么就攤上這事国觉。” “怎么了虾啦?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵麻诀,是天一觀的道長。 經常有香客問我傲醉,道長蝇闭,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任硬毕,我火速辦了婚禮呻引,結果婚禮上,老公的妹妹穿的比我還像新娘吐咳。我一直安慰自己逻悠,他們只是感情好,可當我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布韭脊。 她就那樣靜靜地躺著童谒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪沪羔。 梳的紋絲不亂的頭發(fā)上饥伊,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天,我揣著相機與錄音蔫饰,去河邊找鬼琅豆。 笑死,一個胖子當著我的面吹牛篓吁,可吹牛的內容都是我干的茫因。 我是一名探鬼主播,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼杖剪,長吁一口氣:“原來是場噩夢啊……” “哼节腐!你這毒婦竟也來了?” 一聲冷哼從身側響起摘盆,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎饱苟,沒想到半個月后孩擂,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡箱熬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年类垦,在試婚紗的時候發(fā)現自己被綠了狈邑。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡蚤认,死狀恐怖米苹,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情砰琢,我是刑警寧澤蘸嘶,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站陪汽,受9級特大地震影響训唱,放射性物質發(fā)生泄漏。R本人自食惡果不足惜挚冤,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一况增、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧训挡,春花似錦澳骤、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至表悬,卻和暖如春弥锄,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蟆沫。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工籽暇, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人饭庞。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓戒悠,卻偏偏與公主長得像,于是被迫代替她去往敵國和親舟山。 傳聞我的和親對象是個殘疾皇子绸狐,可洞房花燭夜當晚...
    茶點故事閱讀 45,086評論 2 355

推薦閱讀更多精彩內容

  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法累盗,內部類的語法寒矿,繼承相關的語法,異常的語法若债,線程的語...
    子非魚_t_閱讀 31,644評論 18 399
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理符相,服務發(fā)現,斷路器,智...
    卡卡羅2017閱讀 134,672評論 18 139
  • 小編費力收集:給你想要的面試集合 1.C++或Java中的異常處理機制的簡單原理和應用啊终。 當JAVA程序違反了JA...
    八爺君閱讀 4,594評論 1 114
  • 多態(tài) 任何域的訪問操作都將有編譯器解析镜豹,如果某個方法是靜態(tài)的,它的行為就不具有多態(tài)性 java默認對象的銷毀順序與...
    yueyue_projects閱讀 944評論 0 1
  • 2017年10月21日,我參加了小康哥和紅紅姐的婚禮例衍。如果不是你昔期,我又怎么會飛了幾百公里,去參加這場無關緊要的婚禮...
    左離殤閱讀 507評論 0 0