欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

學(xué)習(xí)Java之Java中的異常處理機(jī)制詳解

 更新時(shí)間:2023年08月08日 08:22:12   作者:一一哥Sun  
在本文中,小編將帶領(lǐng)大家來學(xué)習(xí)Java的異常處理機(jī)制,包括異常機(jī)制、異常類型、如何捕獲異常、如何拋出異常以及如何創(chuàng)建自定義異常等核心內(nèi)容,感興趣的同學(xué)跟著小編一起來看看吧

一. 異常機(jī)制簡(jiǎn)介

1. 異常概念

所謂的異常,其實(shí)就是各種“意外”,是指在程序執(zhí)行期間發(fā)生的“意外事件”,它中斷了正在執(zhí)行程序的正常指令流,沒有產(chǎn)生我們預(yù)期中的結(jié)果。就好比我們的生活中,也會(huì)經(jīng)常有一些意外發(fā)生。本來你計(jì)劃今天和女朋友去happy,結(jié)果你的領(lǐng)導(dǎo)非要你去加班,不加班就辭退,這就是預(yù)期外的異常事件。

Java給我們提供了專門的異常類來處理異常。在一個(gè)方法的運(yùn)行過程中,如果發(fā)生了異常,這個(gè)方法會(huì)產(chǎn)生代表該異常的一個(gè)對(duì)象,并把它交給運(yùn)行時(shí)系統(tǒng),運(yùn)行時(shí)系統(tǒng)會(huì)尋找相應(yīng)的代碼來處理該異常。Java把異常提交給運(yùn)行時(shí)系統(tǒng)的過程稱為拋出(throw)異常,運(yùn)行時(shí)系統(tǒng)在方法的調(diào)用棧中查找到處理該異常對(duì)象的過程稱為捕獲(catch)異常。

2. 產(chǎn)生原因

在Java中,一個(gè)異常的產(chǎn)生主要有以下幾種原因:

  • Java內(nèi)部錯(cuò)誤導(dǎo)致了異常,比如Java虛擬機(jī)自身出現(xiàn)了問題;
  • 我們自己編寫的代碼有問題,例如空指針異常、數(shù)組越界異常等;
  • 項(xiàng)目運(yùn)行所依賴的外部數(shù)據(jù)、網(wǎng)絡(luò)環(huán)境等有問題,導(dǎo)致項(xiàng)目產(chǎn)生了故障;
  • 通過throw等語句主動(dòng)生成異常,主要用來告知該方法的調(diào)用者一些必要信息。

3. 異常類型

我們現(xiàn)在知道,Java中有專門的異常處理類,而這些異常類其實(shí)都是java.lang.Throwable的子類,所以Throwable是所有異常類的“老祖宗”。 從整體上來看,Throwable類中有兩個(gè)異常分支,即Exception和Error。如下圖所示:

從上圖中我們可知,Throwable是所有異常和錯(cuò)誤的父類,Error和 Exception兩個(gè)子類分別表示錯(cuò)誤和異常。

其中,Error錯(cuò)誤是在程序執(zhí)行期間發(fā)生的嚴(yán)重問題,例如虛擬機(jī)崩潰、堆棧溢出錯(cuò)誤、內(nèi)存溢出等。這些錯(cuò)誤一般是正常情況下不大可能出現(xiàn)的,絕大部分的Error都會(huì)導(dǎo)致程序處于非正常、不可恢復(fù)的狀態(tài),而我們也無法處理這些錯(cuò)誤,只能盡力避免它們的發(fā)生,所以一般也不需要被開發(fā)者捕獲處理。

而Exception類則用于處理用戶程序可能出現(xiàn)的異常。根據(jù)異常的產(chǎn)生時(shí)機(jī),該類可以細(xì)分為運(yùn)行時(shí)異常(Runtime Exception)和非運(yùn)行時(shí)異常(UnRuntime Exception) ;或者根據(jù)是否檢查,又可以叫做非受檢異常(Unchecked Exception)和受檢異常(Checked Exception)

  • 運(yùn)行時(shí)異常都是RuntimeException類及其子類,如NullPointerException、IndexOutOfBoundsException、ArithmeticException等。這些異常是在運(yùn)行時(shí)才會(huì)被發(fā)現(xiàn)的異常,它們通常是由于程序員的錯(cuò)誤引起的,例如除零、數(shù)組越界等。我們?cè)诔绦蛑锌梢赃x擇捕獲處理,也可以不處理,但應(yīng)該盡力避免它們發(fā)生。另外因?yàn)檫@些異常在編譯階段通常不會(huì)進(jìn)行異常的檢查,所以也被稱為非受檢異常。
  • 非運(yùn)行時(shí)異常是指RuntimeException以外的異常,它們都是Exception類及其子類。這些異常是在編譯階段就被檢查的異常,也稱為受檢異常。它們通常是由于外部因素引起的,例如輸入/輸出錯(cuò)誤、網(wǎng)絡(luò)連接問題或文件找不到等。我們必須處理這些異常,否則編譯時(shí)就會(huì)出錯(cuò)而無法通過,如IOException、SQLException、ClassNotFoundException及用戶自定義的Exception等異常(我們一般不會(huì)自定義檢查異常)。

4. 小結(jié)

綜上述所, java.lang.Throwable是Java中的異常父類,包括Error和Exception兩大子類。并且在Java代碼中,只有繼承了Throwable類的實(shí)例,才能被throw拋出或者catch捕獲。

4.1 Error與Exception的區(qū)別

Error是正常情況下不大可能出現(xiàn)的情況,屬于未檢查類型,大多數(shù)發(fā)生在運(yùn)行時(shí)。另外絕大部分的Error都會(huì)導(dǎo)致程序處于非正常、不可恢復(fù)的狀態(tài),任何處理技術(shù)都無法恢復(fù),肯定會(huì)導(dǎo)致程序的非正常終止,所以不需要被開發(fā)者捕獲。

而Exception是程序正常運(yùn)行過程中可以預(yù)料到的意外情況,分為受檢異常和非受檢異常。受檢異常在代碼中必須進(jìn)行顯式地捕獲處理,這是編譯期檢查的一部分。非受檢異常也被稱為運(yùn)行時(shí)異常,通常是在編碼時(shí)就能避免的邏輯錯(cuò)誤,具體根據(jù)需要來判斷是否需要捕獲,不會(huì)在編譯器強(qiáng)制要求,應(yīng)該被開發(fā)者捕獲進(jìn)行相應(yīng)的處理。

接下來再給大家說一些常見的Error和Exception:

4.2 錯(cuò)誤

  • OutOfMemoryError:內(nèi)存溢出錯(cuò)誤;
  • VirtualMachineError:虛擬機(jī)錯(cuò)誤;
  • NoClassDefFoundError:找不到類定義錯(cuò)誤;
  • StackOverflowError:堆棧異常錯(cuò)誤

4.3 運(yùn)行時(shí)異常

  • NullPropagation:空指針異常;
  • ClassCastException:強(qiáng)制類型轉(zhuǎn)換異常;
  • IllegalArgumentException:非法傳參異常;
  • IndexOutOfBoundsException:下標(biāo)越界異常;
  • NumberFormatException:數(shù)字格式化異常

4.4 非運(yùn)行時(shí)異常

  • ClassNotFoundException:找不到指定的類異常;
  • IOException:IO操作異常

二. 異常處理機(jī)制

1. 概述

既然異常的產(chǎn)生是不可避免的,那么為了保證程序有效地執(zhí)行,我們就需要對(duì)發(fā)生的異常進(jìn)行相應(yīng)的處理。否則當(dāng)Java程序發(fā)生異常時(shí),可能會(huì)導(dǎo)致程序的停止或故障。而Java給我們提供了一套完整的異常處理機(jī)制,來應(yīng)對(duì)可能出現(xiàn)的各種問題。在Java中,異常處理主要是利用5個(gè)關(guān)鍵字來實(shí)現(xiàn):

try、catch、throw、throws、finally

其中,try catch語句用于捕獲并處理異常,finally語句用于在任何情況下(除特殊情況外)都必須執(zhí)行的代碼,throw語句用于拋出異常,throws語句用于聲明可能會(huì)出現(xiàn)的異常。

總之,Java的異常處理機(jī)制給我們提供了一種結(jié)構(gòu)性和控制性的方式,來處理程序執(zhí)行期間發(fā)生的事件。總體上來說,對(duì)異常的處理其實(shí)就是“要么捕獲,要么拋出” ,這好比我們對(duì)待一個(gè)犯了錯(cuò)誤的孩子,要么抓住他修理一頓,要么把他扔給別人處理,而自己不管不問。所以我們對(duì)異常的處理思路如下:

  • 捕獲異常:在方法中用 try catch語句捕獲并處理異常,catch語句可以有多個(gè),用來匹配多個(gè)異常;
  • 拋出異常:對(duì)處理不了的異?;蛘咭D(zhuǎn)型的異常,在方法的聲明處可以通過throws語句拋出異常,即由上層的調(diào)用方法進(jìn)行處理。

接下來再分別細(xì)說一下異常處理機(jī)制。

2. 捕獲異常

很多時(shí)候,我們對(duì)異常的處理就是進(jìn)行捕獲,所以Java給我們提供了try-catch語句來捕獲異常。如果我們編寫的某些代碼,可能會(huì)拋出異常,那你就可以用try語句塊把這些代碼包裹起來。而catch語句塊中包含了處理異常的代碼,所以如果一個(gè)異常被拋出,它就可以被catch語句塊捕獲并處理。

try {
    // 可能會(huì)拋出異常的代碼
} catch (ExceptionType1 e1) {
    // 異常處理代碼
} catch (ExceptionType2 e2) {
    // 異常處理代碼
} finally {
    // finally塊是可選的,并不是必須的,不管是否發(fā)生異常,這里的代碼都會(huì)被執(zhí)行
}

在try語句塊中,我們可以編寫多個(gè)語句,包括方法調(diào)用、循環(huán)和條件語句等。如果try語句中的某行代碼產(chǎn)生了異常,該異常被拋出,則該語句之后的其他語句就不會(huì)再被執(zhí)行,程序會(huì)直接跳轉(zhuǎn)到與該異常匹配的catch語句塊中。catch語句塊中的異常參數(shù)提供了有關(guān)異常的詳細(xì)信息,例如異常類型、異常消息和堆棧跟蹤等內(nèi)容。

我們可以同時(shí)使用多個(gè)catch語句塊來處理不同類型的異常。在這種情況下,catch語句塊的順序就很重要,因?yàn)楫惓5奶幚頃?huì)與catch語句塊的順序匹配。如果一個(gè)異??梢云ヅ涠鄠€(gè)catch語句塊,則只有第一個(gè)匹配的語句塊會(huì)被執(zhí)行。

finally語句塊是可選的,不管是否發(fā)生異常,finally里的代碼都會(huì)被執(zhí)行。我們通常是在finally語句塊中執(zhí)行一些清理操作,比如關(guān)閉文件或釋放資源等。

3. 拋出異常

我們除了可以捕獲異常外,還可以在代碼中手動(dòng)地通過throw語句來拋出異常。

if (x < 0) {
    throw new IllegalArgumentException("x不能為負(fù)數(shù)");
}

在上面的例子中,我們規(guī)定,如果x小于0,就手動(dòng)拋出一個(gè)IllegalArgumentException異常,并將消息“x不能為負(fù)數(shù)”傳遞給異常。該異??梢允侨魏蜹hrowable的子類,包括我們的自定義異常類。

4. 自定義異常

Java也允許我們創(chuàng)建自己的異常類。為了創(chuàng)建一個(gè)自定義的異常類,我們一般是繼承擴(kuò)展Exception或RuntimeException類,如下所示。

public class MyException extends Exception {
    public MyException() {}
    public MyException(String message) {
        super(message);
    }
}

在上面的例子中,創(chuàng)建了一個(gè)自定義的異常類MyException,它擴(kuò)展了Exception類。我們還提供了兩個(gè)構(gòu)造函數(shù),一個(gè)不帶參數(shù),另一個(gè)帶有一個(gè)字符串參數(shù),用于設(shè)置異常消息。

5. 異常處理的最佳實(shí)踐

在Java中,異常處理是非常重要的,但也容易被濫用,下面是給大家總結(jié)的一些處理異常的最佳實(shí)踐。

5.1 不要捕獲過多的異常

捕獲過多的異常可能會(huì)使代碼難以理解和維護(hù),我們通常是只捕獲必要的異常,并在可能的情況下將它們向上拋出,讓更高層次的代碼來處理它們。

5.2 不要忽略異常

忽略異??赡軙?huì)使程序在后續(xù)的步驟中出現(xiàn)錯(cuò)誤,進(jìn)而導(dǎo)致數(shù)據(jù)出現(xiàn)損壞或其他不良后果。我們一般是在catch語句塊中處理異常,并使用日志來記錄異常信息,以便更好地了解問題。

5.3 不要在finally塊中返回值

在finally語句塊中返回值可能會(huì)導(dǎo)致不可預(yù)測(cè)的行為。如果一個(gè)方法在try語句塊中返回了一個(gè)值,在finally語句塊中又返回了另一個(gè)值,這可能會(huì)導(dǎo)致錯(cuò)誤的結(jié)果。我們?cè)趂inally語句塊中只應(yīng)該執(zhí)行清理操作,不應(yīng)該返回值。

5.4 將異常轉(zhuǎn)換

在某些情況下,我們可能需要將一個(gè)異常轉(zhuǎn)換為另一個(gè)異常。例如,我們想編寫一個(gè)庫,并且我們希望隱藏該庫的某些內(nèi)部實(shí)現(xiàn)細(xì)節(jié),此時(shí)可以將一個(gè)異常轉(zhuǎn)換為另一個(gè)更通用的異常類型,以便客戶端代碼可以更容易地處理它。比如在下面的這個(gè)案例中,就用MyLibraryException替換了IOException。

public class MyLibrary {
    public void doSomething() throws MyLibraryException {
        try {
            // 執(zhí)行一些操作
        } catch (IOException e) {
            //拋出一個(gè)更通用的異常,用MyLibraryException替換IOException
            throw new MyLibraryException("發(fā)生了錯(cuò)誤", e);
        }
    }
}
//自定義一個(gè)更通用的異常
public class MyLibraryException extends Exception {
    public MyLibraryException() {}
    public MyLibraryException(String message) {
        super(message);
    }
    public MyLibraryException(String message, Throwable cause) {
        super(message, cause);
    }
}

在上面的例子中,創(chuàng)建了一個(gè)自定義的異常類MyLibraryException,它擴(kuò)展了Exception類。在MyLibrary類中,如果發(fā)生了IOException,我們就將其轉(zhuǎn)換為MyLibraryException,并將原始異常作為原因傳遞。

5.5 不要在構(gòu)造函數(shù)中拋出異常

在Java中,如果我們?cè)跇?gòu)造函數(shù)中拋出異常,則對(duì)象可能就無法完全初始化了,這可能會(huì)導(dǎo)致在后續(xù)的步驟中出現(xiàn)錯(cuò)誤。所以我們最好避免在構(gòu)造函數(shù)中拋出異常,并使用工廠方法或靜態(tài)工廠方法來創(chuàng)建對(duì)象。

public class MyClass {
    private int x;
    private int y;
    public MyClass(int x, int y) {
        this.x = x;
        if (y < 0) {
            throw new IllegalArgumentException("y不能為負(fù)數(shù)");
        }
        this.y = y;
    }
    public static MyClass create(int x, int y) {
        if (y < 0) {
            throw new IllegalArgumentException("y不能為負(fù)數(shù)");
        }
        return new MyClass(x, y);
    }
}

在上面的例子中,使用了一個(gè)create工廠方法來創(chuàng)建MyClass對(duì)象。如果y為負(fù)數(shù),則在創(chuàng)建對(duì)象之前會(huì)拋出一個(gè)IllegalArgumentException異常。

6. 異常處理時(shí)的常見問題

我們?cè)谶M(jìn)行異常處理時(shí),也有一些常見的問題需要注意。

6.1 不要捕獲Throwable

Throwable是所有異常的超類,包括Error和Exception。開發(fā)時(shí)我們不能捕獲Throwable,因?yàn)樗赡軙?huì)捕獲到一些嚴(yán)重的錯(cuò)誤,如OutOfMemoryError,這些錯(cuò)誤是無法通過代碼處理的。所以在開發(fā)時(shí),我們應(yīng)該去捕獲某個(gè)具體的異常類型。

6.2 不要在finally中拋出異常

如果我們?cè)趂inally語句塊中拋出異常,有可能會(huì)導(dǎo)致之前拋出的異常被覆蓋,這可能會(huì)導(dǎo)致其他的一些錯(cuò)誤。所以我們?cè)趂inally語句塊中,一般只是進(jìn)行清理操作,而不是拋出異常。

6.3 不要忽略InterruptedException

InterruptedException是一個(gè)非常特殊的異常,它通常表示線程被中斷。如果我們要在執(zhí)行長(zhǎng)時(shí)間操作的線程上捕獲InterruptedException,應(yīng)該盡快停止線程并退出。如果繼續(xù)執(zhí)行,可能會(huì)導(dǎo)致一些無法預(yù)料的行為。

6.4 不要使用異常來控制流程

在某些情況下,我們可能會(huì)使用異常機(jī)制來控制程序的流程,但這并不是一種好的實(shí)踐。這會(huì)使代碼難以理解,還可能會(huì)導(dǎo)致性能問題。例如,下面的代碼中就使用了異常機(jī)制來控制循環(huán)的流程:

try {
    while (true) {
        // 一些操作
        if (someCondition) {
            throw new RuntimeException("循環(huán)已經(jīng)完成");
        }
    }
} catch (RuntimeException e) {
    // 處理異常
}

這種做法雖然在語法上是可行的,但如果我們想結(jié)束while循環(huán),更好的辦法是使用一個(gè)標(biāo)志位來控制循環(huán)的流程,而不是使用異常機(jī)制。

boolean done = false;
while (!done) {
    // 一些操作
    if (someCondition) {
        done = true;
    }
}

6.5 不要忽略異常

我們?cè)诰帉懘a時(shí),有可能會(huì)忽略掉異常,但這會(huì)導(dǎo)致代碼無法處理一些錯(cuò)誤情況。在捕獲異常時(shí),我們應(yīng)該始終記錄異?;虼蛴‘惓6褩8?,以便更好地弄清楚產(chǎn)生錯(cuò)誤的原因。

try {
    // 一些操作
} catch (Exception e) {
    logger.error("發(fā)生了錯(cuò)誤", e);
}

在上面的例子中,使用了日志記錄器來記錄異常,并將異常堆棧跟蹤作為額外信息傳遞。

6.6 不要在循環(huán)中捕獲異常

如果我們?cè)谘h(huán)內(nèi)部捕獲異??赡軙?huì)導(dǎo)致性能問題,并讓代碼更難理解。通常是將循環(huán)體封裝在一個(gè)try語句塊中,而不是在循環(huán)內(nèi)部捕獲異常。

try {
    for (int i = 0; i < list.size(); i++) {
        // 一些操作
    }
} catch (Exception e) {
    logger.error("發(fā)生了錯(cuò)誤", e);
}

在上面的例子中,我們使用try語句塊來包裝循環(huán)體,而不是在循環(huán)內(nèi)部捕獲異常。

四. 結(jié)語

Java的異常處理機(jī)制是一種強(qiáng)大的工具,可以幫助我們處理各種異常情況。所以熟練掌握異常處理機(jī)制的基礎(chǔ)知識(shí)和最佳實(shí)踐,可以幫助我們編寫更健壯、可靠的代碼。

我們?cè)诰帉懘a時(shí),應(yīng)該提前考慮到各種異常情況,并在可能的情況下使用異常機(jī)制來處理這些情況。要注意,異常處理機(jī)制應(yīng)該是代碼的一部分,而不是控制流程的一部分。同時(shí),還應(yīng)該注意避免常見的異常處理問題,例如捕獲Throwable、在finally塊中拋出異常、忽略InterruptedException等。并且我們還要注意保持代碼的簡(jiǎn)潔性和可讀性。

以上就是學(xué)習(xí)Java之Java中的異常處理機(jī)制詳解的詳細(xì)內(nèi)容,更多關(guān)于Java異常處理機(jī)制的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • java基于mongodb實(shí)現(xiàn)分布式鎖的示例代碼

    java基于mongodb實(shí)現(xiàn)分布式鎖的示例代碼

    本文主要介紹了java基于mongodb實(shí)現(xiàn)分布式鎖,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • Java 進(jìn)階使用 Lambda 表達(dá)式實(shí)現(xiàn)超強(qiáng)的排序功能

    Java 進(jìn)階使用 Lambda 表達(dá)式實(shí)現(xiàn)超強(qiáng)的排序功能

    今天要說的是第二種排序方式,在內(nèi)存中實(shí)現(xiàn)數(shù)據(jù)排序。這篇文章主要介紹了Java 進(jìn)階使用 Lambda 表達(dá)式實(shí)現(xiàn)超強(qiáng)的排序功能,需要的朋友可以參考下
    2021-11-11
  • idea pom導(dǎo)入net.sf.json的jar包失敗的解決方案

    idea pom導(dǎo)入net.sf.json的jar包失敗的解決方案

    JSON(JavaScript Object Notation,JS對(duì)象簡(jiǎn)譜)是一種輕量級(jí)的數(shù)據(jù)交換格式,這篇文章主要介紹了idea pom導(dǎo)入net.sf.json的jar包失敗的解決方案,感興趣的朋友一起看看吧
    2023-11-11
  • java -length的三種用法說明

    java -length的三種用法說明

    這篇文章主要介紹了java -length的三種用法說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • 解析ConcurrentHashMap: 預(yù)熱(內(nèi)部一些小方法分析)

    解析ConcurrentHashMap: 預(yù)熱(內(nèi)部一些小方法分析)

    ConcurrentHashMap是由Segment數(shù)組結(jié)構(gòu)和HashEntry數(shù)組結(jié)構(gòu)組成。Segment的結(jié)構(gòu)和HashMap類似,是一種數(shù)組和鏈表結(jié)構(gòu),今天給大家普及java面試常見問題---ConcurrentHashMap知識(shí),一起看看吧
    2021-06-06
  • Spring?JDBC?框架簡(jiǎn)介

    Spring?JDBC?框架簡(jiǎn)介

    Spring?JDBC?提供幾種方法和數(shù)據(jù)庫中相應(yīng)的不同的類與接口。我將給出使用JdbcTemplate類框架的經(jīng)典和最受歡迎的方法。本文給大家介紹Spring?JDBC?框架的相關(guān)知識(shí),感興趣的朋友一起看看吧
    2021-12-12
  • SpringCloud Config使用本地倉庫及map注入

    SpringCloud Config使用本地倉庫及map注入

    這篇文章主要介紹了SpringCloud Config使用本地倉庫及map注入,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09
  • Eclipse設(shè)置svn忽略文件或文件夾(svn:ignore)的操作

    Eclipse設(shè)置svn忽略文件或文件夾(svn:ignore)的操作

    這篇文章主要介紹了Eclipse設(shè)置svn忽略文件或文件夾(svn:ignore)的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01
  • Java中集合遍歷的方法示例代碼展示

    Java中集合遍歷的方法示例代碼展示

    在 Java 編程中,集合(Collection)是用于存儲(chǔ)和操作一組對(duì)象的重要工具,無論是數(shù)組、列表(List)、集合(Set),還是映射(Map),它們都提供了在不同場(chǎng)景下靈活使用的數(shù)據(jù)結(jié)構(gòu),這篇文章主要介紹了Java中集合遍歷的方法示例代碼展示,需要的朋友可以參考下
    2024-08-08
  • Java Springboot的目的你知道嗎

    Java Springboot的目的你知道嗎

    在本篇文章中小編給大家分析了Java中Spring Boot的優(yōu)勢(shì)以及相關(guān)知識(shí)點(diǎn)內(nèi)容,興趣的朋友們可以學(xué)習(xí)參考下,希望能夠給你帶來幫助
    2021-09-09

最新評(píng)論