Java基礎(chǔ)-異常-異常處理關(guān)鍵字

Java工程師知識樹 / Java基礎(chǔ)


異常處理關(guān)鍵字

Java異常處理機(jī)制用到的幾個關(guān)鍵字:try、catch戈钢、finally、throw、throws。

  • try:用于監(jiān)聽危喉。將要被監(jiān)聽的代碼(可能拋出異常的代碼)放在try語句塊之內(nèi)驼唱,當(dāng)try語句塊內(nèi)發(fā)生異常時彤委,異常就被拋出铐尚。
  • catch:用于捕獲異常拨脉。catch用來捕獲try語句塊中發(fā)生的異常。
  • finally:finally語句塊總是會被執(zhí)行宣增。它主要用于回收在try塊里打開的物力資源(如數(shù)據(jù)庫連接玫膀、網(wǎng)絡(luò)連接和磁盤文件)。只有finally塊爹脾,執(zhí)行完成之后匆骗,才會回來執(zhí)行try或者catch塊中的return或者throw語句,如果finally中使用了return或者throw等終止方法的語句誉简,則就不會跳回執(zhí)行碉就,直接停止。
  • throw:用于拋出異常闷串。
  • throws:用在方法簽名中瓮钥,用于聲明該方法可能拋出的異常。

final烹吵、finally碉熄、finalize的區(qū)別與用法

final:用于聲明屬性,方法和類肋拔,分別表示屬性不可變锈津,方法不可覆蓋,類不可繼承凉蜂。
finally:是異常處理語句結(jié)構(gòu)的一部分琼梆,表示總是執(zhí)行。
finalize:是Object類的一個方法窿吩,在垃圾收集器執(zhí)行的時候會調(diào)用被回收對象的此方法茎杂,供垃圾收集時的其他資源回收,例如關(guān)閉文件等纫雁。

Try-with-resources

環(huán)境

Java1.7版本及其以后版本

語法

JDK1.7開始煌往,java引入了 try-with-resources 聲明,將 try-catch-finally 簡化為 try-catch轧邪,這其實(shí)是一種語法糖刽脖,在編譯時會進(jìn)行轉(zhuǎn)化為 try-catch-finally 語句。
新的聲明包含三部分:try-with-resources 聲明忌愚、try 塊曲管、catch 塊。它要求在 try-with-resources 聲明中定義的變量實(shí)現(xiàn)了 AutoCloseable 接口菜循,這樣在系統(tǒng)可以自動調(diào)用它們的close方法翘地,從而替代了finally中關(guān)閉資源的功能。

所有實(shí)現(xiàn)了 java.lang.AutoCloseable接口(其中癌幕,它包括實(shí)現(xiàn)了java.io.Closeable 的所有對象)衙耕,可以使用作為資源。

try-with-resources 聲明在 JDK 9 得到改進(jìn)勺远。如果你已經(jīng)有一個資源是 final 或等效于 final 變量,您可以在try-with-resources語句中使用該變量橙喘,而無需在try-with-resources語句中聲明一個新變量。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
 
public class Tester {
   public static void main(String[] args) throws IOException {
      System.out.println(readData("test"));
   } 
   static String readData(String message) throws IOException {
      Reader inputString = new StringReader(message);
      BufferedReader br = new BufferedReader(inputString);
      try (br) {//在 Java 9 中胶逢,不需要聲明資源 br就可以使用它厅瞎,并得到相同的結(jié)果。
         return br.readLine();
      }
   }
}

作用

關(guān)閉在try-catch語句塊中使用的資源初坠,需要在ry-with-resources 聲明中的實(shí)現(xiàn)AutoCloseable 接口的資源和簸。

使用范例

Java1.7之前寫法

public static void main(String[] args) {
    FileInputStream file = null;
    try {
        file = new FileInputStream("D:\\logs\\log-cleaner.log");
        System.out.println("ooo");
        file.read();
        System.out.println("aaa");
    } catch (IOException io) {
        System.out.println("bbb");
        io.printStackTrace();
    } catch (Exception e) {
        System.out.println("ccc");
        e.printStackTrace();
    } finally {
        if (file != null) {
            try {
                file.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

使用JDK1.9之前的 try-with-resources異常處理機(jī)制

public static void main(String[] args) {
    try(FileInputStream file = new FileInputStream("D:\\logs\\log-cleaner.log")){
        System.out.println("ooo");
        file.read();
        System.out.println("aaa");
    }catch (IOException io){
        System.out.println("bbb");
        io.printStackTrace();
    }catch (Exception e){
        System.out.println("ccc");
        e.printStackTrace();
    }
}

編譯后的class文件

public static void main(String[] paramArrayOfString)
{
    try
    {
        FileInputStream localFileInputStream = new FileInputStream("D:\\logs\\log-cleaner.log"); 
        Object localObject1 = null;
        try { 
            System.out.println("ooo");
            localFileInputStream.read();
            System.out.println("aaa");
        }
        catch (Throwable localThrowable2)
        {
            localObject1 = localThrowable2; throw localThrowable2;
        }
        finally
        {
            if (localFileInputStream != null) if (localObject1 != null) try { localFileInputStream.close(); } catch (Throwable localThrowable3) { localObject1.addSuppressed(localThrowable3); } else localFileInputStream.close();
        }
    } catch (IOException localIOException) {
        System.out.println("bbb");
        localIOException.printStackTrace();
    } catch (Exception localException) {
        System.out.println("ccc");
        localException.printStackTrace();
    }
}

return與finally的執(zhí)行順序

public class TestException {


    public static void main(String[] args) {
        System.out.println("-------------");
        System.out.println(div());//try中有return,且try中不拋異常碟刺。
        /*結(jié)果:
        process try
        process finally
        0
         */
        System.out.println("-------------");
        System.out.println(divE());//catch中有return锁保,且try中拋異常。
        /*結(jié)果:
        process try
        process catch
        process finally
        2
         */
        System.out.println("-------------");
        System.out.println(divEr());//catch半沽,finally中都有return爽柒,且try中拋異常。
        /*
        process try
        process catch
        process finally
        3
         */
    }
    public static int div() {
        int result = 0;
        try {
            System.out.println("process try");
            return result;//如果try和catch的return是一個變量時且函數(shù)的是從其中一個返回時者填,后面finally中語句即使有對返回的變量進(jìn)行賦值的操作時浩村,也不會影響返回的值。
        } catch (ArithmeticException e) {
            result = 2;
            System.out.println("process catch");//
        } finally {
            result = 3;//finally中語句對返回的變量進(jìn)行賦值的操作時占哟,也不會影響返回的值
            System.out.println("process finally");//
        }
        return result;
    }
    public static int divE() {
        int result = 0;
        try {
            System.out.println("process try");
            int proces = 1/0;
            return result;
        } catch (ArithmeticException e) {
            result = 2;
            System.out.println("process catch");
            return result;//如果try和catch的return是一個變量時且函數(shù)的是從其中一個返回時心墅,后面finally中語句即使有對返回的變量進(jìn)行賦值的操作時,也不會影響返回的值榨乎。
        } finally {
            result = 3;//finally中語句對返回的變量進(jìn)行賦值的操作時嗓化,也不會影響返回的值
            System.out.println("process finally");
        }
    }

    public static int divEr() {
        int result = 0;
        try {
            System.out.println("process try");
            result = 1/0;
            return result;
        } catch (ArithmeticException e) {
            result = 2;
            System.out.println("process catch");
//            throw new ArithmeticException("divEr執(zhí)行異常");// finally 里有return,這里throw失效
            return result;// finally 里有return谬哀,這里return失效
        } finally {
            result = 3;
            System.out.println("process finally");
            return result;//finally塊中的return語句會阻止異常的棧調(diào)用傳輸刺覆,使divEr認(rèn)為該方法已經(jīng)正常返回
        }
    }

}

通過上面代碼可以得出結(jié)論:

  • 當(dāng)finally有返回值時,會直接返回史煎。不會再去返回try或者catch中的返回值谦屑。
  • 如果try和catch的return是一個變量時且函數(shù)的是從其中一個返回時,后面finally中語句即使有對返回的變量進(jìn)行賦值的操作時篇梭,也不會影響返回的值氢橙。

原因通過反編譯插件查看Class文件:

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市恬偷,隨后出現(xiàn)的幾起案子悍手,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件坦康,死亡現(xiàn)場離奇詭異竣付,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)滞欠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進(jìn)店門古胆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人筛璧,你說我怎么就攤上這事逸绎。” “怎么了夭谤?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵棺牧,是天一觀的道長。 經(jīng)常有香客問我朗儒,道長陨帆,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任采蚀,我火速辦了婚禮疲牵,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘榆鼠。我一直安慰自己纲爸,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布妆够。 她就那樣靜靜地躺著识啦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪神妹。 梳的紋絲不亂的頭發(fā)上颓哮,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天,我揣著相機(jī)與錄音鸵荠,去河邊找鬼冕茅。 笑死,一個胖子當(dāng)著我的面吹牛蛹找,可吹牛的內(nèi)容都是我干的姨伤。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼庸疾,長吁一口氣:“原來是場噩夢啊……” “哼乍楚!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起届慈,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤徒溪,失蹤者是張志新(化名)和其女友劉穎忿偷,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體臊泌,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鲤桥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了缺虐。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡礁凡,死狀恐怖高氮,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情顷牌,我是刑警寧澤剪芍,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站窟蓝,受9級特大地震影響罪裹,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜运挫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一状共、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧谁帕,春花似錦峡继、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至儡循,卻和暖如春舶吗,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背择膝。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工誓琼, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人肴捉。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓踊赠,卻偏偏與公主長得像,于是被迫代替她去往敵國和親每庆。 傳聞我的和親對象是個殘疾皇子筐带,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評論 2 345

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

  • 引言 在程序運(yùn)行過程中(注意是運(yùn)行階段,程序可以通過編譯)缤灵,如果JVM檢測出一個不可能執(zhí)行的操作伦籍,就會出現(xiàn)運(yùn)行時錯...
    Steven1997閱讀 2,401評論 1 6
  • 一蓝晒、前言 ??只要寫過Java代碼,基本上都會遇到異常帖鸦,由于以前學(xué)習(xí)的不夠系統(tǒng)芝薇,所以趁現(xiàn)在有時間,再來重新回顧及梳...
    騎著烏龜去看海閱讀 740評論 0 2
  • 1. 概述 在本文中, 我們將介紹Java 中異常處理的基礎(chǔ)知識作儿,及其一些常見的坑. 2. 前置知識 2.1. 什...
    bern85閱讀 725評論 0 0
  • JAVA 異常類型結(jié)構(gòu) Error 和 Exeption 受查異常和非受查異常 異常的拋出與捕獲 直接拋出異常 封...
    哦00閱讀 389評論 0 0
  • 1洛二、概述 當(dāng)方法內(nèi)部發(fā)生一項錯誤時,該方法會創(chuàng)建一個對象傳遞給運(yùn)行時系統(tǒng)(runtime system)攻锰,這個對象...
    冰河winner閱讀 419評論 0 1