原文地址:http://blog.csdn.net/tiantiandjava/article/details/46777051
今天學習大神的文章:深入理解java異常處理機制 學到一個有意思的知識點。如果在finally中使用return會喫掉catch中拋出的異常。
看例子:
- 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, finally; return value=false
testEx, finally; return value=false
有點奇怪,下層方法拋出的異常竟然沒有被捕獲。
如果把return和throw放在一起,直接會提示錯誤。"Unreachable statement"(無法被執行).
然而finally卻可以成功騙過編譯器讓兩者並存(是不是可以算是編譯器的一個小bug呢),結果是後執行的會覆蓋前者。finally如果有return會覆蓋catch裏的throw,同樣如果finally裏有throw會覆蓋catch裏的return。
進而如果catch裏和finally都有return finally中的return會覆蓋catch中的。throw也是如此。
這樣就好理解一些了,retrun和throw都是使程序跳出當前的方法,自然就是衝突的。如果非要跳出兩次那麼後者會覆蓋前者。
在《java編程思想》中也有類似的例子,放在這裏一起討論。
“9.6.2 缺點:丟失的違例
一般情況下,Java的違例實施方案都顯得十分出色。不幸的是,它依然存在一個缺點。儘管違例指出程序裏存在一個危機,而且絕不應忽略,但一個違例仍有可能簡單地“丟失”。在採用finally從句的一種特殊配置下,便有可能發生這種情況”
- class VeryImportantException extends Exception{
- public String toString(){
- return "A very important exception";
- }
- }
- class HoHumException extends Exception{
- public String toString() {
- return "A trivial exception";
- }
- }
- public class LostMessage {
- void f() throws VeryImportantException{
- throw new VeryImportantException();
- }
- void dispose() throws HoHumException{
- throw new HoHumException();
- }
- public static void main(String[] args) throws Exception{
- LostMessage lm = new LostMessage();
- try{
- lm.f();
- }finally {
- lm.dispose();
- }
- }
- }
輸出:
Exception in thread "main" A trivial exception
at com.test.exception.LostMessage.dispose(LostMessage.java:24)
at com.test.exception.LostMessage.main(LostMessage.java:32)
“這是一項相當嚴重的缺陷,因爲它意味着一個違例可能完全丟失。而且就象前例演示的那樣,這種丟失顯得非常“自然”,很難被人查出蛛絲馬跡。而與此相反,C++裏如果第二個違例在第一個違例得到控制前產生,就會被當作一個嚴重的編程錯誤處理。或許Java以後的版本會糾正這個問題(上述結果是用Java 1.1生成的)。”