Java catch块内抛出异常-是否再次捕获?

Java catch块内抛出异常-是否再次捕获?,java,exception,Java,Exception,这可能看起来像是一个编程101问题,我本以为我知道答案,但现在发现自己需要再次检查。在下面的这段代码中,第一个catch块中抛出的异常是否会被下面的常规异常catch块捕获 try { // Do something } catch(IOException e) { throw new ApplicationException("Problem connecting to server"); } catch(Exception e) { // Will the Application

这可能看起来像是一个编程101问题,我本以为我知道答案,但现在发现自己需要再次检查。在下面的这段代码中,第一个catch块中抛出的异常是否会被下面的常规异常catch块捕获

try {
  // Do something
} catch(IOException e) {
  throw new ApplicationException("Problem connecting to server");
} catch(Exception e) {
  // Will the ApplicationException be caught here?
}

我一直以为答案是否定的,但现在我有一些奇怪的行为,可能是由这引起的。大多数语言的答案可能都是一样的,但我用的是Java。

不,因为新的
throw
不直接在
try
块中。

不——正如Chris Jester Young所说,它将被抛出到层次结构中的下一个try catch中。

如上所述……

我想补充一点,如果你看不清发生了什么,如果你不能在调试器中重现问题,你可以在重新抛出新异常之前添加一个跟踪(更糟糕的是,使用好的旧System.out.println,使用像log4j这样的好日志系统)。

不,这很容易检查

public class Catch {
    public static void main(String[] args) {
        try {
            throw new java.io.IOException();
        } catch (java.io.IOException exc) {
            System.err.println("In catch IOException: "+exc.getClass());
            throw new RuntimeException();
        } catch (Exception exc) {
            System.err.println("In catch Exception: "+exc.getClass());
        } finally {
            System.err.println("In finally");
        }
    }
}
应打印:

In catch IOException: class java.io.IOException In finally Exception in thread "main" java.lang.RuntimeException at Catch.main(Catch.java:8) 在catch IOException中:类java.io.IOException 终于 线程“main”java.lang.RuntimeException中的异常 at Catch.main(Catch.java:8) 从技术上讲,这可能是一个编译器错误、依赖于实现、未指定的行为或其他原因。然而,JLS已经非常明确,编译器对于这类简单的事情来说已经足够好了(泛型案例可能是另一回事)

还要注意的是,如果您交换两个catch块,它将无法编译。第二个陷阱是完全不可能实现的


注意,即使执行了catch块,finally块也始终运行(除了愚蠢的情况,例如无限循环、通过tools接口连接、终止线程、重写字节码等)。

第二个catch块不会捕获finally块。仅当在try块中时,才会捕获每个异常。不过,您可以尝试嵌套(一般来说,这不是一个好主意):


不,因为catch都引用同一个try块,所以从catch块内进行的抛出将被一个封闭的try块捕获(可能在调用此块的方法中)

Java语言规范在第14.19.1节中说:

如果try块的执行由于抛出值V而突然完成,则有一个选择:

  • 如果V的运行时类型可分配给try语句的任何catch子句的参数,则选择第一个(最左边的)catch子句。值V被分配给所选catch子句的参数,并执行该catch子句的块。如果该块正常完成,则try语句正常完成如果该块由于任何原因突然完成,则try语句也会因为同样的原因突然完成。
参考:

换句话说,第一个可以处理异常的封闭捕获会处理异常,如果从该捕获中抛出异常,则该异常不在原始尝试的任何其他捕获的范围内,因此他们不会尝试处理它


需要知道的一件相关且令人困惑的事情是,在try-[catch]-finally结构中,finally块可能会抛出异常,如果是这样,try或catch块抛出的任何异常都将丢失。第一次看到它时可能会感到困惑。

如果要从catch块抛出异常,必须通知方法/类等,它需要抛出所述异常。像这样:

public void doStuff() throws MyException {
    try {
        //Stuff
    } catch(StuffException e) {
        throw new MyException();
    }
}
现在,编译器不会对您大喊大叫:)

旧帖子,但“e”变量必须是唯一的:

try {
  // Do something
} catch(IOException ioE) {
  throw new ApplicationException("Problem connecting to server");
} catch(Exception e) {
  // Will the ApplicationException be caught here?
}

也许您可以描述一下“奇怪的行为”?您确定ApplicationException没有被抛出到其他地方并传播到这个块吗?我在Eclipse IDE中注意到了这一点。这是轮胎迫使我把“抛出新的异常”在一个尝试块,但我不知道为什么。我过去做过,但没有这样做。我不明白为什么需要try块。谷歌上的许多例子表明,人们不需要try块。这是因为我在if语句中插入了一条语句吗?避免
最后出现
的最明显方法当然是调用
系统。退出
:-P@ChrisJester Young
代表(;)较短,包含在语言中,不会带来太多副作用,对我来说,更明显。
System.exit
对CPU更友好!:-O但是是的,好的,很明显这是一个主观标准。还有,我不知道你是一个密码高尔夫球手这应该是评论,而不是回答。它没有提供任何解决实际问题的方法—它只是对OPs问题的批评。只是想补充一点,因为Java 7可以避免在资源中使用
try
。然后,如果
try
finally
都抛出,
finally
被抑制,但也被添加到
try
的异常中。如果
catch
也抛出,你就没有运气了,除非你自己通过'addsupprested'并添加
try
exception来处理,那么你就拥有了这三个异常。假设代码是这样的,那么就试试{}catch(exception e){System.err.println(“in catch exception:+e.getClass());}catch(IOException e){System.err.println(在catch IOException中:“+e.getClass());}try块中的代码会生成IO异常,它会进入即时通用异常块还是会飞到IOException catch块?@user3705478为了避免这种错误情况,代码不会编译。通常,在同一try块中捕获子类的超类之后,不允许子类捕获。t汉克斯。所以我会得到一个编译时错误,对吗?我回家后会测试它。这取决于@user3705478,如果从
catch
块抛出
RuntimeException
,就不会有编译错误了。@AndrewDunn我不认为这是user3705478的问题所在,而是,如果一个父级
try {
  // Do something
} catch(IOException ioE) {
  throw new ApplicationException("Problem connecting to server");
} catch(Exception e) {
  // Will the ApplicationException be caught here?
}