解析Java中未被捕獲的異常以及try語句的嵌套使用
Java未被捕獲的異常
在你學(xué)習(xí)在程序中處理異常之前,看一看如果你不處理它們會(huì)有什么情況發(fā)生是很有好處的。下面的小程序包括一個(gè)故意導(dǎo)致被零除錯(cuò)誤的表達(dá)式。
class Exc0 {
public static void main(String args[]) {
int d = 0;
int a = 42 / d;
}
}
當(dāng)Java運(yùn)行時(shí)系統(tǒng)檢查到被零除的情況,它構(gòu)造一個(gè)新的異常對(duì)象然后拋出該異常。這導(dǎo)致Exc0的執(zhí)行停止,因?yàn)橐坏┮粋€(gè)異常被拋出,它必須被一個(gè)異常處理程序捕獲并且被立即處理。該例中,我們沒有提供任何我們自己的異常處理程序,所以異常被Java運(yùn)行時(shí)系統(tǒng)的默認(rèn)處理程序捕獲。任何不是被你程序捕獲的異常最終都會(huì)被該默認(rèn)處理程序處理。默認(rèn)處理程序顯示一個(gè)描述異常的字符串,打印異常發(fā)生處的堆棧軌跡并且終止程序。
下面是由標(biāo)準(zhǔn)javaJDK運(yùn)行時(shí)解釋器執(zhí)行該程序所產(chǎn)生的輸出:
java.lang.ArithmeticException: / by zero at Exc0.main(Exc0.java:4)
注意,類名Exc0,方法名main,文件名Exc0.java和行數(shù)4是怎樣被包括在一個(gè)簡(jiǎn)單的堆棧使用軌跡中的。還有,注意拋出的異常類型是Exception的一個(gè)名為ArithmeticException的子類,該子類更明確的描述了何種類型的錯(cuò)誤方法。本章后面部分將討論,Java提供多個(gè)內(nèi)置的與可能產(chǎn)生的不同種類運(yùn)行時(shí)錯(cuò)誤相匹配的異常類型。
堆棧軌跡將顯示導(dǎo)致錯(cuò)誤產(chǎn)生的方法調(diào)用序列。例如,下面是前面程序的另一個(gè)版本,它介紹了相同的錯(cuò)誤,但是錯(cuò)誤是在main( )方法之外的另一個(gè)方法中產(chǎn)生的:
class Exc1 {
static void subroutine() {
int d = 0;
int a = 10 / d;
}
public static void main(String args[]) {
Exc1.subroutine();
}
}
默認(rèn)異常處理器的堆棧軌跡結(jié)果表明了整個(gè)調(diào)用棧是怎樣顯示的:
java.lang.ArithmeticException: / by zero at Exc1.subroutine(Exc1.java:4) at Exc1.main(Exc1.java:7)
如你所見,棧底是main的第7行,該行調(diào)用了subroutine( )方法。該方法在第4行導(dǎo)致了異常。調(diào)用堆棧對(duì)于調(diào)試來說是很重要的,因?yàn)樗槊髁藢?dǎo)致錯(cuò)誤的精確的步驟。
Java try語句的嵌套
Try語句可以被嵌套。也就是說,一個(gè)try語句可以在另一個(gè)try塊內(nèi)部。每次進(jìn)入try語句,異常的前后關(guān)系都會(huì)被推入堆棧。如果一個(gè)內(nèi)部的try語句不含特殊異常的catch處理程序,堆棧將彈出,下一個(gè)try語句的catch處理程序?qū)z查是否與之匹配。這個(gè)過程將繼續(xù)直到一個(gè)catch語句匹配成功,或者是直到所有的嵌套try語句被檢查耗盡。如果沒有catch語句匹配,Java的運(yùn)行時(shí)系統(tǒng)將處理這個(gè)異常。下面是運(yùn)用嵌套try語句的一個(gè)例子:
// An example of nested try statements.
class NestTry {
public static void main(String args[]) {
try {
int a = args.length;
/* If no command-line args are present,the following statement will generate a divide-by-zero exception. */
int b = 42 / a;
System.out.println("a = " + a);
try { // nested try block
/* If one command-line arg is used,then a divide-by-zero exception will be generated by the following code. */
if(a==1) a = a/(a-a); // division by zero
/* If two command-line args are used,then generate an out-of-bounds exception. */
if(a==2) {
int c[] = { 1 };
c[42] = 99; // generate an out-of-bounds exception
}
} catch(ArrayIndexOutOfBoundsException e) {
System.out.println("Array index out-of-bounds: " + e);
}
} catch(ArithmeticException e) {
System.out.println("Divide by 0: " + e);
}
}
}
如你所見,該程序在一個(gè)try塊中嵌套了另一個(gè)try塊。程序工作如下:當(dāng)你在沒有命令行參數(shù)的情況下執(zhí)行該程序,外面的try塊將產(chǎn)生一個(gè)被零除的異常。程序在有一個(gè)命令行參數(shù)條件下執(zhí)行,由嵌套的try塊產(chǎn)生一個(gè)被零除的錯(cuò)誤。因?yàn)閮?nèi)部的塊不匹配這個(gè)異常,它將把異常傳給外部的try塊,在那里異常被處理。如果你在具有兩個(gè)命令行參數(shù)的條件下執(zhí)行該程序,由內(nèi)部try塊產(chǎn)生一個(gè)數(shù)組邊界異常。下面的結(jié)果闡述了每一種情況:
C:\>java NestTry Divide by 0: java.lang.ArithmeticException: / by zero C:\>java NestTry One a = 1 Divide by 0: java.lang.ArithmeticException: / by zero C:\>java NestTry One Two a = 2 Array index out-of-bounds: java.lang.ArrayIndexOutOfBoundsException
當(dāng)有方法調(diào)用時(shí),try語句的嵌套可以很隱蔽的發(fā)生。例如,你可以把對(duì)方法的調(diào)用放在一個(gè)try塊中。在該方法內(nèi)部,有另一個(gè)try語句。這種情況下,方法內(nèi)部的try仍然是嵌套在外部調(diào)用該方法的try塊中的。下面是前面例子的修改,嵌套的try塊移到了方法nesttry( )的內(nèi)部:
/* Try statements can be implicitly nested via calls to methods. */
class MethNestTry {
static void nesttry(int a) {
try { // nested try block
/* If one command-line arg is used,then a divide-by-zero exception will be generated by the following code. */
if(a==1) a = a/(a-a); // division by zero
/* If two command-line args are used,then generate an out-of-bounds exception. */
if(a==2) {
int c[] = { 1 };
c[42] = 99; // generate an out-of-bounds exception
}
} catch(ArrayIndexOutOfBoundsException e) {
System.out.println("Array index out-of-bounds: " + e);
}
}
public static void main(String args[]) {
try {
int a = args.length;
/* If no command-line args are present,the following statement will generate a divide-by-zero exception. */
int b = 42 / a;
System.out.println("a = " + a);
nesttry(a);
} catch(ArithmeticException e) {
System.out.println("Divide by 0: " + e);
}
}
}
該程序的輸出與前面的例子相同。
相關(guān)文章
記錄一個(gè)使用Spring?Data?JPA設(shè)置默認(rèn)值的問題
這篇文章主要介紹了使用Spring?Data?JPA設(shè)置默認(rèn)值的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
SpringBoot快速實(shí)現(xiàn)接口消息加密的過程詳解
在項(xiàng)目中,為了保證數(shù)據(jù)的安全,我們常常會(huì)對(duì)傳遞的數(shù)據(jù)進(jìn)行加密,常用的加密算法包括對(duì)稱加密(AES)和非對(duì)稱加密(RSA),博主選取碼云上最簡(jiǎn)單的API加密項(xiàng)目進(jìn)行下面的講解,需要的朋友可以參考下2023-11-11
SpringBoot+Mybatis實(shí)現(xiàn)登錄注冊(cè)的示例代碼
這篇文章主要介紹了SpringBoot+Mybatis實(shí)現(xiàn)登錄注冊(cè)的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
Java實(shí)戰(zhàn)之基于TCP實(shí)現(xiàn)簡(jiǎn)單聊天程序
這篇文章主要為大家詳細(xì)介紹了如何在Java中基于TCP實(shí)現(xiàn)簡(jiǎn)單聊天程序,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
Spring?Boot整合流控組件Sentinel的場(chǎng)景分析
Sentinel?提供簡(jiǎn)單易用、完善的?SPI?擴(kuò)展接口。您可以通過實(shí)現(xiàn)擴(kuò)展接口來快速地定制邏輯,這篇文章主要介紹了Spring?Boot整合流控組件Sentinel的過程解析,需要的朋友可以參考下2021-12-12
Mybatis有查詢結(jié)果但存不進(jìn)實(shí)體類的解決方案
這篇文章主要介紹了Mybatis有查詢結(jié)果但存不進(jìn)實(shí)體類的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-11-11
springboot整合curator實(shí)現(xiàn)分布式鎖過程
這篇文章主要介紹了springboot整合curator實(shí)現(xiàn)分布式鎖過程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05

