Java學(xué)習(xí)之異常處理的新特性詳解
一. 異常處理新特性
異常處理機(jī)制是Java很早時(shí)就搞出來(lái)的技術(shù),但在實(shí)際應(yīng)用中,我們發(fā)現(xiàn)這個(gè)異常處理也有一些不完善的地方。比如在操作IO流時(shí)經(jīng)常需要關(guān)閉IO資源,這些代碼就得放在finally代碼塊中,而在finally中關(guān)閉IO流時(shí),又會(huì)提示我們需要再次捕獲異常?;蛘哂袝r(shí)我們?cè)谝粋€(gè)方法中,同時(shí)要捕獲多個(gè)異常,這就需要使用多個(gè)catch代碼塊。但這樣一來(lái),我們寫出來(lái)的代碼就顯得特別啰嗦繁瑣,所以很多Java程序員就很希望能夠簡(jiǎn)化這種操作。而Java團(tuán)隊(duì)也很重視大家的反饋,在新的JDK版本中對(duì)此進(jìn)行了相關(guān)的優(yōu)化,接下來(lái)就給大家說(shuō)一下關(guān)于異常處理的新特性。
1. 多異常捕獲
1.1 存在的問題
我們先來(lái)回顧一下在使用try-catch多重結(jié)構(gòu)時(shí)存在的問題,比如下面這樣的代碼:
try{
// 可能會(huì)發(fā)生異常的語(yǔ)句
} catch (FileNotFoundException e) {
// 調(diào)用方法methodA處理
} catch (IOException e) {
// 調(diào)用方法methodA處理
} catch (ParseException e) {
// 調(diào)用方法methodA處理
} catch(...){
....
}相信大家對(duì)上面這樣的代碼塊已經(jīng)不陌生了,這種多catch的代碼塊雖然客觀上提高了程序的健壯性,但也讓我們的代碼量大大的增加,可讀性降低了很多。其實(shí)代碼中雖然有些異常的種類不同,但如果捕獲之后的處理是相同的,那是否可以把多個(gè)異常合并在一起處理呢?
1.2 解決辦法
為了解決多catch代碼塊的問題,在JDK 7中,Java開始支持”多異常捕獲“技術(shù),允許我們把多個(gè)異常進(jìn)行合并處理。我們來(lái)看看如下案例:
public static void main(String[] args) {
try {
int a = Integer.parseInt("100");
int b = a / 0;
System.out.println("b=" + b);
} catch (IndexOutOfBoundsException | NumberFormatException | ArithmeticException e) {
System.out.println("異常信息="+e.getMessage());
e.printStackTrace();
// 捕獲多個(gè)異常時(shí),異常對(duì)象e的前面默認(rèn)有final修飾,e對(duì)象不能被重新賦值
// 否則會(huì)產(chǎn)生如下異常:The parameter e of a multi-catch block cannot be assigned
//e = new ArithmeticException("test");
} catch (Exception e) {
System.out.println("e,異常信息="+e.getMessage());
e.printStackTrace();
// 捕獲一種類型的異常時(shí),異常變量沒有final修飾,e變量可以被重新賦值
e = new RuntimeException("test");
}
}在上面的代碼中,我們?cè)谝粋€(gè)catch()中同時(shí)捕獲了”IndexOutOfBoundsException | NumberFormatException | ArithmeticException“多個(gè)異常對(duì)象。但是我們要注意,在捕獲多個(gè)異常對(duì)象時(shí),異常對(duì)象e的前面默認(rèn)會(huì)帶有final修飾,所以e對(duì)象就不能再被重新賦值,否則會(huì)產(chǎn)生如下異常:The parameter e of a multi-catch block cannot be assigned。而默認(rèn)的單個(gè)異常對(duì)象捕獲時(shí),并不會(huì)帶有final修飾符。
1.3 小結(jié)
根據(jù)上面的案例,再把本節(jié)內(nèi)容給大家總結(jié)一下:
- 捕獲多種類型異常時(shí),多種異常類型之間要用豎線 | 隔開;
- 捕獲多種類型異常時(shí),異常變量前默認(rèn)帶有隱式的final修飾,我們不能再對(duì)異常變量重新賦值。
2. 自動(dòng)資源管理
2.1 概述
在Java中,我們經(jīng)常需要管理一些資源,例如文件、數(shù)據(jù)庫(kù)連接、網(wǎng)絡(luò)連接等。在使用完這些資源后,我們需要關(guān)閉它們以釋放系統(tǒng)資源,否則可能會(huì)導(dǎo)致系統(tǒng)崩潰或資源泄漏。在以前的代碼實(shí)現(xiàn)中,經(jīng)常需要在finally代碼塊中對(duì)這些資源進(jìn)行關(guān)閉,最終寫出來(lái)的代碼就特別啰嗦。
后來(lái)JDK 7給我們?cè)黾恿艘粋€(gè)新特性,該特性可以自動(dòng)關(guān)閉資源文件,被稱為自動(dòng)資源管理(Automatic Resource Management,簡(jiǎn)稱ARM) 。這樣,我們?cè)谔幚懋惓r(shí),就可以利用自動(dòng)資源管理來(lái)正確地管理這些資源,避免因?yàn)橥涥P(guān)閉資源而導(dǎo)致一些問題。
2.2 自動(dòng)資源管理
所謂的自動(dòng)資源管理,是指我們?cè)谑褂肐O流等物理資源時(shí),程序會(huì)自動(dòng)為我們釋放這些資源,無(wú)需再手動(dòng)調(diào)用關(guān)閉資源的方法。自動(dòng)資源管理主要是通過try-with-resources語(yǔ)句進(jìn)行實(shí)現(xiàn),該語(yǔ)句是從JDK 7版本中開始引入的。但如果我們想使用該功能,需要滿足以下兩個(gè)條件:
物理資源對(duì)象必須實(shí)現(xiàn)AutoCloseable接口或其子接口Closeable,Closeable接口只有一個(gè)close()方法,用于關(guān)閉資源。
try-with-resources的代碼塊只能使用try語(yǔ)句中聲明的資源對(duì)象。
AutoCloseable接口是在Java 7中新增的接口,用于指示資源需要在使用完畢后關(guān)閉。Java 7幾乎把所有的“資源類”(包括各種文件IO類、JDBC的Connection 和 Statement等接口)都進(jìn)行了改寫,改寫后的資源類都實(shí)現(xiàn)了AutoCloseable 或 Closeable接口。這樣當(dāng)try-with-resources語(yǔ)句執(zhí)行完成后,Java就會(huì)自動(dòng)調(diào)用資源對(duì)象的close()方法釋放資源。即使try語(yǔ)句塊中發(fā)生了異常,也會(huì)自動(dòng)關(guān)閉資源,確保了資源在使用完后被正確的關(guān)閉。
2.3 代碼案例
接下來(lái)再通過一個(gè)代碼案例來(lái)演示自動(dòng)資源管理該如何實(shí)現(xiàn)。
public class Demo10 {
public static void main(String[] args) {
//try中聲明的資源對(duì)象默認(rèn)會(huì)帶有final修飾符,try中可以同時(shí)聲明多個(gè)資源對(duì)象
try(BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}//這里就沒有使用finally代碼,Java會(huì)自動(dòng)關(guān)閉IO流
}
}在上面的例子中,我們就使用了try-with-resources語(yǔ)句來(lái)讀取一個(gè)文件,try語(yǔ)句中聲明的資源會(huì)被隱式聲明為final,且在一條try語(yǔ)句中可以同時(shí)聲明或初始化多個(gè)資源。BufferedReader和FileReader都實(shí)現(xiàn)了AutoCloseable接口,因此在使用完之后,它們會(huì)被自動(dòng)關(guān)閉。
而且你會(huì)發(fā)現(xiàn),其實(shí)try-with-resources的用法和try-catch是一樣的,但不用我們?cè)倬帉慺inally代碼了。這是因?yàn)樽詣?dòng)關(guān)閉資源中的try語(yǔ)句,相當(dāng)于包含了隱式的finally塊,這個(gè)finally塊會(huì)自動(dòng)關(guān)閉資源。所以這樣我們就可以簡(jiǎn)化代碼,避免代碼中出現(xiàn)大量的 try-catch塊和finally塊,使代碼更加簡(jiǎn)潔易讀,而且能夠自動(dòng)處理多個(gè)資源的關(guān)閉,避免了繁瑣的手動(dòng)關(guān)閉操作。
2.4 增強(qiáng)的自動(dòng)資源管理
雖然JDK 7中的自動(dòng)資源管理已經(jīng)讓我們的代碼很簡(jiǎn)化了,但很多人覺得還是不夠,所以在JDK 9中又再次增強(qiáng)了自動(dòng)資源管理功能。JDK 9允許我們將多個(gè)資源變量放在try語(yǔ)句后的圓括號(hào)中,但不要求我們?cè)趖ry語(yǔ)句的圓括號(hào)中聲明并創(chuàng)建資源,只需要把自動(dòng)關(guān)閉的資源帶有final修飾即可。 接下來(lái)再通過一個(gè)案例給大家演示一下JDK 9的特性。
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
/**
* @author 一一哥Sun
*/
public class Demo11 {
public static void main(String[] args) throws IOException {
//需要在資源對(duì)象前面添加final修飾符
//讀取一個(gè)文件
final FileReader fileReader = new FileReader("file.txt");
final BufferedReader br = new BufferedReader(fileReader);
//JDK 9之后,try()后的括號(hào)中可以同時(shí)捕獲處理多個(gè)資源對(duì)象,會(huì)對(duì)這多個(gè)資源對(duì)象自動(dòng)關(guān)閉
try (fileReader;br){
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}
}
}在上面的案例中,我們需要在資源對(duì)象前面添加final修飾符,并且try()后的括號(hào)中可以同時(shí)捕獲處理多個(gè)資源對(duì)象,多個(gè)對(duì)象之間用分號(hào)";"進(jìn)行分割,最終Java會(huì)對(duì)這多個(gè)資源對(duì)象自動(dòng)關(guān)閉。
2.5 注意事項(xiàng)
我們?cè)谑褂胻ry-with-resources時(shí)需要注意以下幾點(diǎn):
- try-with-resources語(yǔ)句塊中的資源必須實(shí)現(xiàn) AutoCloseable 或Closeable接口,否則編譯器會(huì)報(bào)錯(cuò);
- 在try-with-resources語(yǔ)句塊中,當(dāng)異常拋出時(shí),會(huì)按照資源的創(chuàng)建順序依次關(guān)閉每個(gè)資源;
- 如果在關(guān)閉某個(gè)資源時(shí)拋出了異常,該異常會(huì)被抑制(suppressed),并添加到try塊中拋出的異常中,我們可以通過getSuppressed方法獲取抑制的異常;
- 除了Java標(biāo)準(zhǔn)庫(kù)中自帶的資源對(duì)象,我們也可以自定義資源對(duì)象,自定義資源對(duì)象時(shí)需要實(shí)現(xiàn)AutoCloseable接口或其子接口Closeable。
二. 結(jié)語(yǔ)
至此,就把異常的新特性也給大家講解完畢了.
以上就是Java學(xué)習(xí)之異常處理的新特性詳解的詳細(xì)內(nèi)容,更多關(guān)于Java異常處理特性的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
運(yùn)用Spring?Aop+注解實(shí)現(xiàn)日志記錄
我們都知道Spring框架的兩大特性分別是 IOC (控制反轉(zhuǎn))和 AOP (面向切面),這個(gè)是每一個(gè)Spring學(xué)習(xí)視頻里面一開始都會(huì)提到的,這里,如果我們使用Aop來(lái)記錄日志,那是再好不過了,感興趣的朋友跟隨小編一起學(xué)習(xí)下Spring?Aop注解實(shí)現(xiàn)日志記錄的過程吧2022-01-01
使用JAVA實(shí)現(xiàn)高并發(fā)無(wú)鎖數(shù)據(jù)庫(kù)操作步驟分享
一個(gè)在線2k的游戲,每秒鐘并發(fā)都嚇?biāo)廊?。傳統(tǒng)的hibernate直接插庫(kù)基本上是不可行的。我就一步步推導(dǎo)出一個(gè)無(wú)鎖的數(shù)據(jù)庫(kù)操作,詳情看下文2013-11-11
一學(xué)即會(huì)之JDK版本快速切換方法(2024)
這篇文章主要介紹了一學(xué)即會(huì)之JDK版本快速切換方法,詳細(xì)給大家講解了如何下載、安裝和配置多個(gè)JDK版本,并通過設(shè)置環(huán)境變量和編寫批處理腳本來(lái)切換JDK版本,需要的朋友可以參考下2025-03-03
maven pom中內(nèi)置變量及引用的實(shí)現(xiàn)
maven其實(shí)有很多內(nèi)置變量供開發(fā)著在開發(fā)中使用,本文主要介紹了maven pom中內(nèi)置變量及引用的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2024-01-01
java網(wǎng)上圖書商城(4)購(gòu)物車模塊1
這篇文章主要為大家詳細(xì)介紹了java網(wǎng)上圖書商城,購(gòu)物車模塊,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12
mybatis新增save結(jié)束后自動(dòng)返回主鍵id詳解
這篇文章主要介紹了mybatis新增save結(jié)束后自動(dòng)返回主鍵id詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
SpringBoot框架實(shí)現(xiàn)支付和轉(zhuǎn)賬功能
在 Spring Boot 框架中實(shí)現(xiàn)支付和轉(zhuǎn)賬功能時(shí),涉及到多個(gè)細(xì)節(jié)和注意點(diǎn),這些功能通常需要高度的安全性、穩(wěn)定性和可擴(kuò)展性,本文介紹了實(shí)現(xiàn)支付和轉(zhuǎn)賬功能的一些關(guān)鍵點(diǎn),需要的朋友可以參考下2024-08-08
Springboot+AOP實(shí)現(xiàn)時(shí)間參數(shù)格式轉(zhuǎn)換
前端傳過來(lái)的時(shí)間參數(shù),后端可以自定義時(shí)間格式轉(zhuǎn)化使用,這樣想轉(zhuǎn)成什么就轉(zhuǎn)成什么。本文將利用自定義注解AOP實(shí)現(xiàn)時(shí)間參數(shù)格式轉(zhuǎn)換,感興趣的可以了解一下2022-04-04

