finally中使用return会吃掉catch中抛出的异常

原创 2015年07月06日 17:30:07

今天学习大神的文章:深入理解java异常处理机制 学到一个有意思的知识点。如果在finally中使用return会吃掉catch中抛出的异常。

看例子:

[java] view plaincopy
  1. public class TestException {  
  2.     public TestException() {  
  3.     }  
  4.   
  5.     boolean testEx() throws Exception {  
  6.         boolean ret = true;  
  7.         try {  
  8.             ret = testEx1();  
  9.         } catch (Exception e) {  
  10.             System.out.println("testEx, catch exception");  
  11.             ret = false;  
  12.             throw e;  
  13.         } finally {  
  14.             System.out.println("testEx, finally; return value=" + ret);  
  15.             return ret;  
  16.         }  
  17.     }  
  18.   
  19.     boolean testEx1() throws Exception {  
  20.         boolean ret = true;  
  21.         try {  
  22.             ret = testEx2();  
  23.             if (!ret) {  
  24.                 return false;  
  25.             }  
  26.             System.out.println("testEx1, at the end of try");  
  27.             return ret;  
  28.         } catch (Exception e) {  
  29.             System.out.println("testEx1, catch exception");  
  30.             ret = false;  
  31.             throw e;  
  32.         } finally {  
  33.             System.out.println("testEx1, finally; return value=" + ret);  
  34.             return ret;  
  35.         }  
  36.     }  
  37.   
  38.     boolean testEx2() throws Exception {  
  39.         boolean ret = true;  
  40.         try {  
  41.             int b = 12;  
  42.             int c;  
  43.             for (int i = 2; i >= -2; i--) {  
  44.                 c = b / i;  
  45.                 System.out.println("i=" + i);  
  46.             }  
  47.             return true;  
  48.         } catch (Exception e) {  
  49.             System.out.println("testEx2, catch exception");  
  50.             ret = false;  
  51.             throw e;  
  52.         } finally {  
  53.             System.out.println("testEx2, finally; return value=" + ret);  
  54.             return ret;  
  55.         }  
  56.     }  
  57.   
  58.     public static void main(String[] args) {  
  59.         TestException testException1 = new TestException();  
  60.         try {  
  61.             testException1.testEx();  
  62.         } catch (Exception e) {  
  63.             e.printStackTrace();  
  64.         }  
  65.     }  
  66. }  

运行结果:

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生成的)。”

书中的例子更加犀利,我们尽量避免这样的事情发生吧。

有return的情况下try catch finally的执行顺序(最有说服力的总结)

结论: 1、不管有木有出现异常,finally块中代码都会执行; 2、当try和catch中有return时,finally仍然会执行; 3、finally是在return后面的表达式运算后执行...
  • kavensu
  • kavensu
  • 2012年10月13日 17:25
  • 163603

finally语句到底是在return之前还是之后执行?

参考:http://blog.csdn.net/kavensu/article/details/8067850代码示例:http://www.cnblogs.com/lanxuezaipiao/p/3...

java中finally与return的执行顺序详解

一些准备知识:     首先为了说明白java中finally与return的执行顺序是怎样的这个问题,我们需要做一点准备工作。     java方法是在栈幀中执行,栈幀是线程私有栈的单位,执行方法的...

当return遇到finally

在try-catch-finally中, 当return遇到finally:      1.在try catch块里return的时候,finally也会被执行。      2.return 语句...

Java try-catch-finally进行异常处理以及throw主动抛出异常

1.try内声明的变量,类似于局部变量,出了try{}语句,就不能被调用 2.finally是可选的。 3.catch语句内部是对异常对象的处理:      >getMessage();  print...

java悄无声息的吞掉异常

try{                 throw new RuntimeException("test");             }finally{                 Sy...

try ,finally都抛出异常如何处理.如果try中抛出了异常,在控制权转移到调用栈上一层代码之前, finally 语句块也会执行,如果finally抛出异常,try语句快抛出的那个异常就

package com.github.jdk7; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFac...

丢失的违例(小心你的finally)

一般情况下,Java的违例实施方案都显得十分出色。不幸的是,它依然存在一个缺点。尽管违例指出程序里存在一个危机,而且绝不应忽略,但一个违例仍有可能简单地“丢失”。在采用finally从句的一种特殊配置...

finally 中抛出异常处理

在finally 不要return  main:System.out.println(testExp()); public static String testExp() { ...

异常处理中在finally里面写return会怎么样

西城旧梦梦旧人 2017-02-25 22:31 java里面异常模块中finally是肯定会执行的,那么,如果在finally语句块中写了return语句了,会怎么样呢?下面就来试试~~ 程序...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:finally中使用return会吃掉catch中抛出的异常
举报原因:
原因补充:

(最多只允许输入30个字)