在java中,異常處理的機制有哪幾種,分別是什麼 匿名使用者 1級 2006-04-26 回答

1 引子

try…catch…finally恐怕是大家再熟悉不過的語句了,而且感覺用起來也是很簡單,邏輯上似乎也是很容易理解。不過,我親自體驗的“教訓”告訴我,這個東西可不是想象中的那麼簡單、聽話。不信?那你看看下面的程式碼,“猜猜”它執行後的結果會是什麼?不要往後看答案、也不許執行程式碼看真正答案哦。如果你的答案是正確,那麼這篇文章你就不用浪費時間看啦。

package myExample。testException;

public class TestException {

public TestException() {

}

boolean testEx() throws Exception{

boolean ret = true;

try{

ret = testEx1();

}catch (Exception e){

System。out。println(“testEx, catch exception”);

ret = false;

throw e;

}finally{

System。out。println(“testEx, finally; return value=”+ret);

return ret;

}

}

boolean testEx1() throws Exception{

boolean ret = true;

try{

ret = testEx2();

if (!ret){

return false;

}

System。out。println(“testEx1, at the end of try”);

return ret;

}catch (Exception e){

System。out。println(“testEx1, catch exception”);

ret = false;

throw e;

}

finally{

System。out。println(“testEx1, finally; return value=”+ret);

return ret;

}

}

boolean testEx2() throws Exception{

boolean ret = true;

try{

int b=12;

int c;

for (int i=2;i>=-2;i——){

c=b/i;

System。out。println(“i=”+i);

}

return true;

}catch (Exception e){

System。out。println(“testEx2, catch exception”);

ret = false;

throw e;

}

finally{

System。out。println(“testEx2, finally; return value=”+ret);

return ret;

}

}

public static void main(String[] args) {

TestException testException1 = new TestException();

try{

testException1。testEx();

}catch(Exception e){

e。printStackTrace();

}

}

}

你的答案是什麼?是下面的答案嗎?

i=2

i=1

testEx2, catch exception

testEx2, finally; return value=false

testEx1, catch exception

testEx1, finally; return value=false

testEx, catch exception

testEx, finally; return value=false

如果你的答案真的如上面所說,那麼你錯啦。^_^,那就建議你仔細看一看這篇文章或者拿上面的程式碼按各種不同的情況修改、執行、測試,你會發現有很多事情不是原來想象中的那麼簡單的。

現在公佈正確答案:

i=2

i=1

testEx2, catch exception

testEx2, finally; return value=false

testEx1, finally; return value=false

testEx, finally; return value=false

2 基礎知識

2。1 相關概念

例外是在程式執行過程中發生的異常事件,比如除0溢位、陣列越界、檔案找不到等,這些事件的發生將阻止程式的正常執行。為了加強程式的魯棒性,程式設計時,必須考慮到可能發生的異常事件並做出相應的處理。C語言中,透過使用if語句來判斷是否出現了例外,同時,呼叫函式透過被呼叫函式的返回值感知在被呼叫函式中產生的例外事件並進行處理。全程變數ErroNo常常用來反映一個異常事件的型別。但是,這種錯誤處理機制會導致不少問題。

Java透過面向物件的方法來處理例外。在一個方法的執行過程中,如果發生了例外,則這個方法生成代表該例外的一個物件,並把它交給執行時系統,執行時系統尋找相應的程式碼來處理這一例外。我們把生成例外物件並把它提交給執行時系統的過程稱為拋棄(throw)一個例外。執行時系統在方法的呼叫棧中查詢,從生成例外的方法開始進行回朔,直到找到包含相應例外處理的方法為止,這一個過程稱為捕獲(catch)一個例外。

2。2 Throwable類及其子類

用面向物件的方法處理例外,就必須建立類的層次。類 Throwable位於這一類層次的最頂層,只有它的後代才可以做為一個例外被拋棄。圖1表示了例外處理的類層次。

從圖中可以看出,類Throwable有兩個直接子類:Error和Exception。Error類物件(如動態連線錯誤等),由Java虛擬機器生成並拋棄(通常,Java程式不對這類例外進行處理);Exception類物件是Java程式處理或拋棄的物件。它有各種不同的子類分別對應於不同型別的例外。其中類RuntimeException代表執行時由Java虛擬機器生成的例外,如算術運算例外ArithmeticException(由除0錯等導致)、陣列越界例外ArrayIndexOutOfBoundsException等;其它則為非執行時例外,如輸入輸出例外IOException等。Java編譯器要求Java程式必須捕獲或宣告所有的非執行時例外,但對執行時例外可以不做處理。

圖1 例外處理的類層次

2。3 異常處理關鍵字

Java的異常處理是透過5個關鍵字來實現的:try,catch,throw,throws,finally。JB的線上幫助中對這幾個關鍵字是這樣解釋的:

Throws: Lists the exceptions a method could throw。

Throw: Transfers control of the method to the exception handler。

Try: Opening exception-handling statement。

Catch: Captures the exception。

Finally: Runs its code before terminating the program。

2。3。1 try語句

try語句用大括號{}指定了一段程式碼,該段程式碼可能會拋棄一個或多個例外。

2。3。2 catch語句

catch語句的引數類似於方法的宣告,包括一個例外型別和一個例外物件。例外型別必須為Throwable類的子類,它指明瞭catch語句所處理的例外型別,例外物件則由執行時系統在try所指定的程式碼塊中生成並被捕獲,大括號中包含物件的處理,其中可以呼叫物件的方法。

catch語句可以有多個,分別處理不同類的例外。Java執行時系統從上到下分別對每個catch語句處理的例外型別進行檢測,直到找到型別相匹配的catch語句為止。這裡,型別匹配指catch所處理的例外型別與生成的例外物件的型別完全一致或者是它的父類,因此,catch語句的排列順序應該是從特殊到一般。

也可以用一個catch語句處理多個例外型別,這時它的例外型別引數應該是這多個例外型別的父類,程式設計中要根據具體的情況來選擇catch語句的例外處理型別。

2。3。3 finally語句

try所限定的程式碼中,當拋棄一個例外時,其後的程式碼不會被執行。透過finally語句可以指定一塊程式碼。無論try所指定的程式塊中拋棄或不拋棄例外,也無論catch語句的例外型別是否與所拋棄的例外的型別一致,finally所指定的程式碼都要被執行,它提供了統一的出口。通常在finally語句中可以進行資源的清除工作。如關閉開啟的檔案等。

2。3。4 throws語句

throws總是出現在一個函式頭中,用來標明該成員函式可能丟擲的各種異常。對大多數Exception子類來說,Java 編譯器會強迫你宣告在一個成員函式中丟擲的異常的型別。如果異常的型別是Error或 RuntimeException, 或它們的子類,這個規則不起作用, 因為這在程式的正常部分中是不期待出現的。 如果你想明確地丟擲一個RuntimeException,你必須用throws語句來宣告它的型別。

2。3。5 throw語句

throw總是出現在函式體中,用來丟擲一個異常。程式會在throw語句後立即終止,它後面的語句執行不到,然後在包含它的所有try塊中(可能在上層呼叫函式中)從裡向外尋找含有與其匹配的catch子句的try塊。

3 關鍵字及其中語句流程詳解

3。1 try的巢狀

你可以在一個成員函式呼叫的外面寫一個try語句,在這個成員函式內部,寫另一個try語句保護其他程式碼。每當遇到一個try語句,異常的框架就放到堆疊上面,直到所有的try語句都完成。如果下一級的try語句沒有對某種異常進行處理,堆疊就會展開,直到遇到有處理這種異常的try語句。下面是一個try語句巢狀的例子。

class MultiNest {

static void procedure() {

try {

int a = 0;

int b = 42/a;

} catch(java。lang。ArithmeticException e) {

System。out。println(“in procedure, catch ArithmeticException: ” + e);

}

}

public static void main(String args[]) {

try {

procedure();

} catch(java。lang。 Exception e) {

System。out。println(“in main, catch Exception: ” + e);

}

}

}

這個例子執行的結果為:

in procedure, catch ArithmeticException: java。lang。ArithmeticException: / by zero

成員函式procedure裡有自己的try/catch控制,所以main不用去處理 ArrayIndexOutOfBoundsException;當然如果如同最開始我們做測試的例子一樣,在procedure中catch到異常時使用throw e;語句將異常丟擲,那麼main當然還是能夠捕捉並處理這個procedure丟擲來的異常。例如在procedure函式的catch中的System。out語句後面增加throw e;語句之後,執行結果就變為:

in procedure, catch ArithmeticException: java。lang。ArithmeticException: / by zero

in main, catch Exception: java。lang。ArithmeticException: / by zero

3。2 try-catch程式塊的執行流程以及執行結果

相對於try-catch-finally程式塊而言,try-catch的執行流程以及執行結果還是比較簡單的。

首先執行的是try語句塊中的語句,這時可能會有以下三種情況:

1. 如果try塊中所有語句正常執行完畢,那麼就不會有其他的“動做”被執行,整個try-catch程式塊正常完成。

2. 如果try語句塊在執行過程中碰到異常V,這時又分為兩種情況進行處理:

² 如果異常V能夠被與try相應的catch塊catch到,那麼第一個catch到這個異常的catch塊(也是離try最近的一個與異常V匹配的catch塊)將被執行;如果catch塊執行正常,那麼try-catch程式塊的結果就是“正常完成”;如果該catch塊由於原因R突然中止,那麼try-catch程式塊的結果就是“由於原因R突然中止(completes abruptly)”。

² 如果異常V沒有catch塊與之匹配,那麼這個try-catch程式塊的結果就是“由於丟擲異常V而突然中止(completes abruptly)”。

3. 如果try由於其他原因R突然中止(completes abruptly),那麼這個try-catch程式塊的結果就是“由於原因R突然中止(completes abruptly)”。

3。3 try-catch-finally程式塊的執行流程以及執行結果

try-catch-finally程式塊的執行流程以及執行結果比較複雜。

首先執行的是try語句塊中的語句,這時可能會有以下三種情況:

1. 如果try塊中所有語句正常執行完畢,那麼finally塊的居於就會被執行,這時分為以下兩種情況:

² 如果finally塊執行順利,那麼整個try-catch-finally程式塊正常完成。

² 如果finally塊由於原因R突然中止,那麼try-catch-finally程式塊的結局是“由於原因R突然中止(completes abruptly)”

2. 如果try語句塊在執行過程中碰到異常V,這時又分為兩種情況進行處理:

² 如果異常V能夠被與try相應的catch塊catch到,那麼第一個catch到這個異常的catch塊(也是離try最近的一個與異常V匹配的catch塊)將被執行;這時就會有兩種執行結果:

² 如果catch塊執行正常,那麼finally塊將會被執行,這時分為兩種情況:

² 如果finally塊執行順利,那麼整個try-catch-finally程式塊正常完成。

² 如果finally塊由於原因R突然中止,那麼try-catch-finally程式塊的結局是“由於原因R突然中止(completes abruptly)”

² 如果catch塊由於原因R突然中止,那麼finally模組將被執行,分為兩種情況:

² 如果如果finally塊執行順利,那麼整個try-catch-finally程式塊的結局是“由於原因R突然中止(completes abruptly)”。

² 如果finally塊由於原因S突然中止,那麼整個try-catch-finally程式塊的結局是“由於原因S突然中止(completes abruptly)”,原因R將被拋棄。

(注意,這裡就正好和我們的例子相符合,雖然我們在testEx2中使用throw e丟擲了異常,但是由於testEx2中有finally塊,而finally塊的執行結果是complete abruptly的(別小看這個用得最多的return,它也是一種導致complete abruptly的原因之一啊——後文中有關於導致complete abruptly的原因分析),所以整個try-catch-finally程式塊的結果是“complete abruptly”,所以在testEx1中呼叫testEx2時是捕捉不到testEx1中丟擲的那個異常的,而只能將finally中的return結果獲取到。

如果在你的程式碼中期望透過捕捉被呼叫的下級函式的異常來給定返回值,那麼一定要注意你所呼叫的下級函式中的finally語句,它有可能會使你throw出來的異常並不能真正被上級呼叫函式可見的。當然這種情況是可以避免的,以testEx2為例:如果你一定要使用finally而且又要將catch中throw的e在testEx1中被捕獲到,那麼你去掉testEx2中的finally中的return就可以了。

這個事情已經在OMC2。0的MIB中出現過啦:伺服器的異常不能完全被反饋到客戶端。)

² 如果異常V沒有catch塊與之匹配,那麼finally模組將被執行,分為兩種情況:

² 如果finally塊執行順利,那麼整個try-catch-finally程式塊的結局就是“由於丟擲異常V而突然中止(completes abruptly)”。

² 如果finally塊由於原因S突然中止,那麼整個try-catch-finally程式塊的結局是“由於原因S突然中止(completes abruptly)”,異常V將被拋棄。

3. 如果try由於其他原因R突然中止(completes abruptly),那麼finally塊被執行,分為兩種情況:

² 如果finally塊執行順利,那麼整個try-catch-finally程式塊的結局是“由於原因R突然中止(completes abruptly)”。

² 如果finally塊由於原因S突然中止,那麼整個try-catch-finally程式塊的結局是“由於原因S突然中止(completes abruptly)”,原因R將被拋棄。

3。4 try-catch-finally程式塊中的return

從上面的try-catch-finally程式塊的執行流程以及執行結果一節中可以看出無論try或catch中發生了什麼情況,finally都是會被執行的,那麼寫在try或者catch中的return語句也就不會真正的從該函式中跳出了,它的作用在這種情況下就變成了將控制權(語句流程)轉到finally塊中;這種情況下一定要注意返回值的處理。

例如,在try或者catch中return false了,而在finally中又return true,那麼這種情況下不要期待你的try或者catch中的return false的返回值false被上級呼叫函式獲取到,上級呼叫函式能夠獲取到的只是finally中的返回值,因為try或者catch中的return語句只是轉移控制權的作用。

3。5 如何丟擲異常

如果你知道你寫的某個函式有可能丟擲異常,而你又不想在這個函式中對異常進行處理,只是想把它丟擲去讓呼叫這個函式的上級呼叫函式進行處理,那麼有兩種方式可供選擇:

第一種方式:直接在函式頭中throws SomeException,函式體中不需要try/catch。比如將最開始的例子中的testEx2改為下面的方式,那麼testEx1就能捕捉到testEx2丟擲的異常了。

boolean testEx2() throws Exception{

boolean ret = true;

int b=12;

int c;

for (int i=2;i>=-2;i——){

c=b/i;

System。out。println(“i=”+i);

}

return true;

}

第二種方式:使用try/catch,在catch中進行一定的處理之後(如果有必要的話)丟擲某種異常。例如上面的testEx2改為下面的方式,testEx1也能捕獲到它丟擲的異常:

boolean testEx2() throws Exception{

boolean ret = true;

try{

int b=12;

int c;

for (int i=2;i>=-2;i——){

c=b/i;

System。out。println(“i=”+i);

}

return true;

}catch (Exception e){

System。out。println(“testEx2, catch exception”);

Throw e;

}

}

第三種方法:使用try/catch/finally,在catch中進行一定的處理之後(如果有必要的話)丟擲某種異常。例如上面的testEx2改為下面的方式,testEx1也能捕獲到它丟擲的異常:

boolean testEx2() throws Exception{

boolean ret = true;

try{

int b=12;

int c;

for (int i=2;i>=-2;i——){

c=b/i;

System。out。println(“i=”+i);

throw new Exception(“aaa”);

}

return true;

}catch (java。lang。ArithmeticException e){

System。out。println(“testEx2, catch exception”);

ret = false;

throw new Exception(“aaa”);

}finally{

System。out。println(“testEx2, finally; return value=”+ret);

}

}

4 關於abrupt completion

前面提到了complete abruptly(暫且理解為“突然中止”或者“異常結束”吧),它主要包含了兩種大的情形:abrupt completion of expressions and statements,下面就分兩種情況進行解釋。

4。1 Normal and Abrupt Completion of Evaluation

每一個表示式(expression)都有一種使得其包含的計算得以一步步進行的正常模式,如果每一步計算都被執行且沒有異常丟擲,那麼就稱這個表示式“正常結束(complete normally)”;如果這個表示式的計算丟擲了異常,就稱為“異常結束(complete abruptly)”。異常結束通常有一個相關聯的原因(associated reason),通常也就是丟擲一個異常V。

與表示式、運算子相關的執行期異常有:

² A class instance creation expression, array creation expression , or string concatenation operatior expression throws an OutOfMemoryError if there is insufficient memory available。

² An array creation expression throws a NegativeArraySizeException if the value of any dimension expression is less than zero。

² A field access throws a NullPointerException if the value of the object reference expression is null。

² A method invocation expression that invokes an instance method throws a NullPointerException if the target reference is null。

² An array access throws a NullPointerException if the value of the array reference expression is null。

² An array access throws an ArrayIndexOutOfBoundsException if the value of the array index expression is negative or greater than or equal to the length of the array。

² A cast throws a ClassCastException if a cast is found to be impermissible at run time。

² An integer division or integer remainder operator throws an ArithmeticException if the value of the right-hand operand expression is zero。

² An assignment to an array component of reference type throws an ArrayStoreException when the value to be assigned is not compatible with the component type of the array。

4。2 Normal and Abrupt Completion of Statements

正常情況我們就不多說了,在這裡主要是列出了abrupt completion的幾種情況:

² break, continue, and return 語句將導致控制權的轉換,從而使得statements不能正常地、完整地執行。

² 某些表示式的計算也可能從java虛擬機器丟擲異常,這些表示式在上一小節中已經總結過了;一個顯式的的throw語句也將導致異常的丟擲。丟擲異常也是導致控制權的轉換的原因(或者說是阻止statement正常結束的原因)。

如果上述事件發生了,那麼這些statement就有可能使得其正常情況下應該都執行的語句不能完全被執行到,那麼這些statement也就是被稱為是complete abruptly。

導致abrupt completion的幾種原因:

² A break with no label

² A break with a given label

² A continue with no label

² A continue with a given label

² A return with no value

² A return with a given value A

² throw with a given value, including exceptions thrown by the Java virtual machine

5 關於我們的程式設計的一點建議

弄清楚try-catch-finally的執行情況後我們才能正確使用它。

如果我們使用的是try-catch-finally語句塊,而我們又需要保證有異常時能夠丟擲異常,那麼在finally語句中就不要使用return語句了(finally語句塊的最重要的作用應該是釋放申請的資源),因為finally中的return語句會導致我們的throw e被拋棄,在這個try-catch-finally的外面將只能看到finally中的返回值(除非在finally中丟擲異常)。(我們需要記住:不僅throw語句是abrupt completion 的原因,return、break、continue等這些看起來很正常的語句也是導致abrupt completion的原因。)

在java中,異常處理的機制有哪幾種,分別是什麼 匿名使用者 1級 2006-04-27 回答

第一部分 選擇checked or unchecked

這裡需要對異常的理解。什麼算異常?java的異常處理機制是用來幹什麼的?異常和錯誤有什麼區別?

異常機制就是java的錯誤處理機制!java中的異常意味著2點:第一,讓錯誤處理程式碼更有條理。這使得

正常程式碼和錯誤處理程式碼分離。第二,引入了context的概念,認為有些錯誤是可以被處理的。問題就出在這兒了。

java的checked異常指的就是在當前context不能被處理的錯誤!

這句話其實是對上面2點的總結。首先checked異常是一種錯誤,其次這種錯誤可以被處理(或修復)。

checked異常就是可以被處理(修復)的錯誤,unchecked異常其實就是無法處理(修復)的錯誤。

說到這兒,應該清楚了。別的語言沒有checked異常,就是說它們認為錯誤都無法被修復,至少在語言級

不提供錯誤修復的支援。java的catch clause乾的就是錯誤修復的事。

我的理解是,用好java的異常,其實就是搞清楚什麼時候該用checked異常。應該把unchecked異常當作

預設行為。unchecked異常的意思是:當我做這件事時,不可思議的情況發生了,我沒辦法正常工作下去!

然後丟擲一個unchecked異常,程式掛起。而checked異常的意思是:當我做這件事時,有意外情況發生,

可以肯定的是,活是沒法幹了,但是要不要掛起程式,我這個函式沒法做主,我只能彙報上級!

其實,從上面的分析可以看出,java引入checked異常只是讓程式設計師多了一個選擇,它並不強迫你使用checked異常。

如果你對什麼時候應該使用checked異常感到迷惑,那麼最簡單的辦法就是,不要使用checked異常!這裡包括2個

方面:

第一,你自己不必建立新的異常類,也不必在你的程式碼中丟擲checked異常,錯誤發生後只管丟擲unchecked異常;

第二,對已有API的checked異常統統catch後轉為unchecked異常!

使用unchecked異常是最省事的辦法。用這種方法也可以享受“正常程式碼和錯誤處理程式碼分離”的好處。因為我們在呼叫方法時,

不用根據其返回值判斷是否有錯誤出現,只管呼叫,只管做正事就ok了。如果出現錯誤,程式自然會知道並掛起。這樣的效果是怎樣

的呢?

第一,我們的業務程式碼很清晰,基本都是在處理業務問題,而沒有一大堆判斷是否有錯的冗餘程式碼。(想想看,如果沒有

throw異常的機制,你只能透過函式的返回值來判斷錯誤,那麼你在每個呼叫函式的地方都會有判斷程式碼!)

第二,我們的程式碼假設一切正常,如果確實如此,那麼它工作良好。但是一旦出現任何錯誤,程式就會掛起停止執行。當然,你可以檢視

日誌找到錯誤資訊。

那麼使用checked異常又是怎樣的呢?

第一,你需要考慮更多的問題。首先在設計上就會更加複雜,其次就是程式碼更加冗長。設計上覆雜

體現在以下方面:

1 對異常(錯誤)的抽象和理解。你得知道什麼情況才能算checked異常,使得上級確實能夠處理(修復)這種異常,並且讓整個程式

從這種設計中確實得到好處。

2 對整個自定義checked異常繼承體系的設計。正如那篇文章所說,總不能在一個方法後面丟擲20個異常吧!設計自定義checked異常,

就要考慮方法簽名問題,在合適的時候丟擲合適的異常(不能一味的丟擲最具體的異常,也不能一味丟擲最抽象的異常)

第二,業務程式碼相比較使用unchecked的情況而言,不夠直接了當了。引入了throws簽名和catch clause,程式碼裡有很多catch,方法

簽名也和異常綁定了。

第三,有了更強的錯誤處理能力。如果發生了checked異常,我們有能力處理(修復)它。表現在不是任何錯誤都會導致程式掛起,出現了

checked異常,程式可能照樣執行。整個程式更加健壯,而代價就是前面2條。

第二部分 使用checked異常的最佳實踐

現在假設有些錯誤我們確定為checked異常,那麼我們針對這些checked異常要怎樣編碼才合理呢?

1 不要用checked異常做流程控制。無論如何,checked異常也是一種錯誤。只是我們可以處理(修復)它而已。這種錯誤和普通業務

流程還是有區別的,而且從效率上來說,用異常控制業務流程是不划算的。其實這個問題有時候很難界定,因為checked異常“可以修復”,

那麼就是說修復後程序照常執行,這樣一來真的容易跟普通業務流程混淆不清。比如註冊使用者時使用者名稱已經存在的問題。這個時候我們要考慮,

為什麼要用checked異常?這和使用業務流程相比,給我帶來了什麼好處?(注意checked異常可以修復,這是和unchecked異常本質的區別)

照我的理解,checked異常應該是介於正常業務流程和unchecked異常(嚴重錯誤)之間的一種比較嚴重的錯誤。出現了這種錯誤,程式無法

完成正常的功能是肯定的了,但我們可以透過其他方式彌補(甚至修復),總之不會讓程式掛起就是。其實這一點也是設計checked異常時要考慮

的問題,也是代價之一吧。

2 對checked異常的封裝。這裡麵包括2個問題:

第一,如果要建立新的checked異常,儘量包含多一點資訊,如果只是一條message,那麼用Exception好了。當然,用Exception會

失去異常的型別資訊,讓客戶端無法判斷具體型別,從而無法針對特定異常進行處理。

第二,不要讓你要丟擲的checked exception升級到較高的層次。例如,不要讓SQLException延伸到業務層。這樣可以避免方法

簽名後有太多的throws。在業務層將持久層的所有異常統統歸為業務層自定義的一種異常。

3 客戶端呼叫含有throws的方法要注意:

第一,不要忽略異常。既然是checked異常,catch clause裡理應做些有用的事情??修復它!catch裡為空白或者僅僅打印出錯資訊都是

不妥的!為空白就是假裝不知道甚至瞞天過海,但是,出來混遲早要還的,遲早會報unchecked異常並程式掛起!非典就是個例子。

打印出錯資訊也好不到哪裡去,和空白相比除了多幾行資訊沒啥區別。如果checked異常都被這麼用,那真的不如當初都改成unchecked好了,

大家都省事!

第二,不要捕獲頂層的Exception。你這麼幹,就是在犯罪!因為unchecked異常也是一種Exception!你把所有異常都捕獲了??不是我

不相信你的能力,你根本就不知道該如何處理!這樣做的直接的後果就是,你的程式一般來說是不會掛起了,但是出現錯誤的時候功能廢了,

表面上卻看不出什麼!當然,深究起來,這也不是什麼罪大惡極,如果你在catch裡列印了資訊,這和上面那條的情況是差不多的。而這2條

的共同點就是,沒有正確使用checked異常!費了那麼大勁設計的checked異常就是給你們上級(客戶端)用的,結果你們不會用!真的

不如用unchecked乾脆利落了!