成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

Java 異常入門(mén)(1/2)

lucas / 1940人閱讀

摘要:所有能夠處理該異常的方法,都來(lái)自一個(gè)叫做調(diào)用堆棧的方法列表。如果運(yùn)行環(huán)境在調(diào)用堆棧中自始至終未能找到捕獲這個(gè)異常的代碼塊,那么整個(gè)程序?qū)⒔K止運(yùn)行。

本文嘗試以盡可能詳細(xì)的方式介紹 Java 當(dāng)中的異常概念和處理機(jī)制。本文適合 Java 初學(xué)者閱讀。

什么是異常

異常是發(fā)生在程序運(yùn)行過(guò)程中的,阻斷正常流程中的指令執(zhí)行的事件。

當(dāng)一個(gè)方法在執(zhí)行當(dāng)中發(fā)生錯(cuò)誤時(shí),這個(gè)方法就會(huì)創(chuàng)建一個(gè)特別的對(duì)象,將其交付給 Java 運(yùn)行環(huán)境處理。這個(gè)對(duì)象被稱(chēng)作“異常對(duì)象”(或簡(jiǎn)稱(chēng)異常),它當(dāng)中包含了異常事件的類(lèi)型和狀態(tài)等等信息。 創(chuàng)建這個(gè)對(duì)象并將其交付給 Java 運(yùn)行環(huán)境的過(guò)程,稱(chēng)作“拋出異?!?。

  

異常對(duì)象:
所有的異常對(duì)象都繼承于 java.lang.Exception 類(lèi)。不同類(lèi)型的異常被定義成它的不同子類(lèi)。常見(jiàn)的異常類(lèi)型有 java.io.IOException(讀寫(xiě)異常),java.lang.NullPointerException(空指針異常)等。

當(dāng)一個(gè)方法拋出異常(或“異常對(duì)象”)時(shí),運(yùn)行環(huán)境就會(huì)嘗試尋找某個(gè)方法去處理它。所有能夠處理該異常的方法,都來(lái)自一個(gè)叫做“調(diào)用堆棧”的方法列表。這個(gè)列表的最頂層就是拋出該異常的方法,往下是調(diào)用該方法的方法,然后依次類(lèi)推。

例如a()方法當(dāng)中調(diào)用了b()方法,b()方法當(dāng)中調(diào)用了c()方法,那么當(dāng)c()方法拋出異常時(shí),它就在調(diào)用堆棧的最頂層,往下是b()方法,再往下就是a()方法。

運(yùn)行環(huán)境會(huì)沿著調(diào)用堆棧往下尋找,尋找方法當(dāng)中是否存在能夠處理這個(gè)異常的代碼塊。這樣的代碼塊叫做“捕獲異?!?。運(yùn)行環(huán)境將異常對(duì)象交給這個(gè)“捕獲異?!钡拇a塊處理。如果運(yùn)行環(huán)境在調(diào)用堆棧中自始至終未能找到捕獲這個(gè)異常的代碼塊,那么整個(gè)程序?qū)⒔K止運(yùn)行。

處理異常的方式:捕獲或聲明

當(dāng)你編寫(xiě)一個(gè)方法 a(),當(dāng)中調(diào)用了方法 b(),而該方法可能拋出異常,那么你有兩種選擇:

一、在 a() 方法中用 try-catch 結(jié)構(gòu)捕獲 b() 方法拋出的異常,方式如下:

// 示例1
try {
    ...
    b();
    ...
} catch (Exception e) {
    // 處理異常對(duì)象
}

二、在 a() 方法上聲明為拋出 b() 方法所拋出的異常,像這樣:

// 示例2
public void a() throws Exception {
    ...
    b();
    ...
}

這樣的話,調(diào)用 a() 方法的那個(gè)方法,同樣面臨兩種選擇:捕獲,或繼續(xù)拋出。如果你不在這兩種處理方式當(dāng)中選擇一種,那么編譯器就會(huì)判定你的代碼存在錯(cuò)誤,并拒絕編譯。

開(kāi)始的時(shí)候說(shuō)過(guò),異常事件會(huì)阻斷指令的執(zhí)行。也就是說(shuō),執(zhí)行到 b() 方法的時(shí)候,如果它拋出了異常,那么它后面的指令都不會(huì)執(zhí)行了。比如在第一種情況下(示例 1)拋出異常,那么從 b();} catch (Exception e) { 之間的所有語(yǔ)句都不會(huì)執(zhí)行;在第二種情況下(示例 2)則是從 b(); 到 a() 方法結(jié)束之間的所有語(yǔ)句都不會(huì)執(zhí)行。

接下來(lái)我們分別介紹這兩種處理方式。

捕獲異常的方式:try-catch-finally

在 Java 中,捕獲異常的方式是編寫(xiě) try-catch-finally 代碼塊。下面是一個(gè)例子,讀取指定文件并將文件內(nèi)容輸出到控制臺(tái):

// 示例3
public static void main(String[] args) {
    java.io.File file = new File("C:1.txt");
    java.io.BufferedReader reader = null;
    String line;

    try {
        reader = new BufferedReader(
                new java.io.FileReader(file));          // 1

        while ((line = reader.readLine()) != null) {    // 2
            System.out.println(line);
        }

    } catch (IOException e) {                           // 3
        e.printStackTrace();

    } finally {                                         // 4
        if (reader != null) {
            try {
                reader.close();                         // 5
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

上面的例子中,1 處的 new FileReader(file) 和 [2] 處的 readLine() 方法都可能拋出 java.io.IOException,所以我們用 try {...} 將它們包起來(lái),表示這部分代碼執(zhí)行的時(shí)候可能拋出異常。

[3] 處為 catch 塊,這部分決定了當(dāng)異常真的發(fā)生時(shí),該如何處理。假如 1 處拋出了異常,那么 Java 運(yùn)行環(huán)境將跳過(guò) try 塊后面的 while 部分,直接轉(zhuǎn)到 catch 塊來(lái)處理這個(gè)異常。

catch 后面的 (IOException e) 聲明了被捕獲的異常對(duì)象,你可以在 catch 塊中使用它。在這里我們簡(jiǎn)單的調(diào)用 e.printStackTrace() 方法,將異常信息輸出到控制臺(tái)。

注意,try 塊中拋出的異常類(lèi)型必須與 catch 塊聲明所要捕獲的異常類(lèi)型匹配,否則編譯器將拒絕編譯。關(guān)于這一點(diǎn)的詳情將在后面說(shuō)明。

[4] 處為 finally 塊,這部分決定了當(dāng) try 塊和/或 catch 塊執(zhí)行完畢后,還要執(zhí)行哪些代碼,這部分可以看作是“總是會(huì)執(zhí)行的”、“善后工作”。在這里我們嘗試關(guān)閉 reader 對(duì)象,不論是否出現(xiàn)異常。

注意 reader.close(); 方法也可能拋出異常,所以 [5] 這里又需要用 try-catch-finally 塊包起來(lái)。你當(dāng)然已經(jīng)注意到,這里沒(méi)有 finally 部分。其實(shí) try-catch-finally 塊有三種寫(xiě)法,分別是:

1. try {...A...} catch(Exception e) {...B...} finally {...C...}
2. try {...A...} catch(Exception e) {...B...}
3. try {...A...} finally {...C...}

寫(xiě)法 1 的意思是:嘗試 A;如果出現(xiàn)異常則執(zhí)行 B;不管是否出現(xiàn)異常,都執(zhí)行 C。
寫(xiě)法 2 的意思是:嘗試 A;如果出現(xiàn)異常則執(zhí)行 B。
寫(xiě)法 3 的意思是:嘗試 A;如果出現(xiàn)異常則不理會(huì)拋出去;不管是否出現(xiàn)異常,都執(zhí)行 C。

在寫(xiě)法 3 中,如果 try 部分拋出了異常,則需要在當(dāng)前方法中聲明。聲明拋出異常的方式,將在接下來(lái)說(shuō)明。

聲明拋出異常

任何一個(gè)方法都可以通過(guò) throws 關(guān)鍵字聲明自己可能拋出異常。下面是一個(gè)例子:

// 示例4
public void f() throws Exception {
    ...
}

在這個(gè)例子中,方法 f() 聲明自己可能會(huì)拋出 java.lang.Exception 類(lèi)型的異常。除了 Exception 外,方法也可以明確的指出自己可能拋出哪種類(lèi)型的異常,例如:

// 示例5
public void f() throws java.io.IOException {
    ...
}

如果方法當(dāng)中的某條語(yǔ)句可能會(huì)拋出 A 類(lèi)型的異常,那么方法就不能聲明為拋出 B 類(lèi)型的異常。下面的做法是錯(cuò)誤的:

// 示例6
public void g() throws java.lang.NullPointerException {
    f();
}

因?yàn)?f() 已經(jīng)聲明為拋出 IOException,而 g() 并沒(méi)有將該異常捕獲,因此它也必須聲明為 “throws IOException”。如果編譯器發(fā)現(xiàn)這種不匹配的情況,就會(huì)拒絕編譯。

有一種情況例外,就是 B 類(lèi)型的異常是 A 類(lèi)型的異常的父類(lèi)。這意味著 B 類(lèi)型的異常在業(yè)務(wù)邏輯上涵蓋了 A 類(lèi)型,所以我們相信凡是能處理 B 的自然也能處理 A。

因此,既然 java.lang.Exception 是所有異常的父類(lèi),那么凡是聲明拋出該類(lèi)型異常的方法,自然可以拋出任意類(lèi)型的異常。也就是說(shuō),當(dāng)一個(gè)方法聲明為 “throws Exception” 時(shí),它可以拋出任何類(lèi)型的異常。注意,因?yàn)檫@種聲明方式會(huì)給方法的調(diào)用者帶來(lái)困擾,所以我們盡量不要這么做。

  

回顧一下示例 3:
現(xiàn)在回顧一下示例 3 中 catch(IOException e) {...} 部分。如果將它改為 catch(Exception e) {...},就表示捕獲所有類(lèi)型的異常,即它前面的 try 部分不論拋出什么類(lèi)型的異常,它都可以處理。某些情況下這樣做是合理的,因?yàn)槲覀儾幌M?dāng)遇到某個(gè)特定種類(lèi)的異常時(shí),程序終止運(yùn)行。

接下來(lái)請(qǐng)看

Java 異常入門(mén)(2/2)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/64180.html

相關(guān)文章

  • Java 異常入門(mén)(2/2)

    摘要:創(chuàng)建和拋出異常對(duì)象當(dāng)我們的某個(gè)方法執(zhí)行當(dāng)中遇到錯(cuò)誤,無(wú)法繼續(xù)處理的時(shí)候,我們也可以自己創(chuàng)建異常對(duì)象并拋出,交給方法的調(diào)用者處理。拋出異常的方式是使用關(guān)鍵字。如果日期字符串不符合格式,則拋出一個(gè)異常。 創(chuàng)建和拋出異常對(duì)象 當(dāng)我們的某個(gè)方法執(zhí)行當(dāng)中遇到錯(cuò)誤,無(wú)法繼續(xù)處理的時(shí)候,我們也可以自己創(chuàng)建異常對(duì)象并拋出,交給方法的調(diào)用者處理。拋出異常的方式是使用 throw 關(guān)鍵字。下面是一個(gè)例子...

    klinson 評(píng)論0 收藏0
  • Java 新手入門(mén)需要關(guān)注的一些問(wèn)題

    摘要:聲明本文所有列舉的問(wèn)題都來(lái)源于編程隨想的博客,這個(gè)博客的博主知識(shí)淵博,編程方面的一些文章質(zhì)量很高,給人醍醐灌頂?shù)母杏X(jué)。 聲明:本文所有列舉的問(wèn)題都來(lái)源于 《編程隨想》的博客,這個(gè)博客的博主知識(shí)淵博,編程方面的一些文章質(zhì)量很高,給人醍醐灌頂?shù)母杏X(jué)。 算法和數(shù)據(jù)結(jié)構(gòu) 什么時(shí)候該用數(shù)組類(lèi)型容器,什么時(shí)候該用鏈表型容器,如何合理的使用數(shù)據(jù)類(lèi)型 什么是散列函數(shù),HashMap的實(shí)現(xiàn)原理是什么 ...

    zsirfs 評(píng)論0 收藏0
  • Flutter基礎(chǔ)(三)Dart快速入門(mén)

    摘要:工具可以報(bào)告兩種問(wèn)題警告和錯(cuò)誤。警告只是說(shuō)明代碼可能無(wú)法正常工作,但不會(huì)阻止程序執(zhí)行。中的是一組無(wú)序的集合。其中來(lái)指定異常類(lèi)型,來(lái)捕獲異常對(duì)象。其中代表只導(dǎo)入指定的部分,代表除了指定的部分都導(dǎo)入。 本文首發(fā)于微信公眾號(hào)「劉望舒」 前言 Dart是Flutter SDK指定的語(yǔ)言,因此要學(xué)習(xí)Flutter,Dart是必須掌握的。關(guān)于Dart可以寫(xiě)一本書(shū)了,這里用一篇文章來(lái)介紹下Dart的精...

    helloworldcoding 評(píng)論0 收藏0
  • java入門(mén)

    摘要:包含了支持服務(wù)開(kāi)發(fā)的類(lèi),并為提供基礎(chǔ),如語(yǔ)言基礎(chǔ)操作操作網(wǎng)絡(luò)通信以及多線程等技術(shù)。在運(yùn)行文件時(shí),的解釋器對(duì)這些字節(jié)碼進(jìn)行解釋執(zhí)行,執(zhí)行過(guò)程中需要加入的類(lèi)在連接階段被載入到運(yùn)行環(huán)境中。支持多個(gè)線程同時(shí)執(zhí)行,并提供多線程之間的同步機(jī)制。 1.什么是Java語(yǔ)言 簡(jiǎn)單地說(shuō),Java 是由 Sun Microsystems 公司于 1995 年推出的一門(mén)面向?qū)ο蟪绦蛟O(shè)計(jì)語(yǔ)言。2009 年 Or...

    zhangfaliang 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

lucas

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<