Java 在 catch 块内抛出异常 - 会再次被捕获吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/143622/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 08:52:31  来源:igfitidea点击:

Exception thrown inside catch block - will it be caught again?

javaexception

提问by roryf

This may seem like a programming 101 question and I had thought I knew the answer but now find myself needing to double check. In this piece of code below, will the exception thrown in the first catch block then be caught by the general Exception catch block below?

这似乎是一个编程 101 问题,我以为我知道答案,但现在发现自己需要仔细检查。在下面这段代码中,在第一个 catch 块中抛出的异常会被下面的通用 Exception catch 块捕获吗?

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

I always thought the answer would be no, but now I have some odd behaviour that could be caused by this. The answer is probably the same for most languages but I'm working in Java.

我一直认为答案是否定的,但现在我有一些可能由此引起的奇怪行为。大多数语言的答案可能相同,但我使用的是 Java。

采纳答案by Chris Jester-Young

No, since the new throwis not in the tryblock directly.

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

回答by Ian P

No -- As Chris Jester-Young said, it will be thrown up to the next try-catch in the hierarchy.

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

回答by PhiLho

As said above...
I would add that if you have trouble seeing what is going on, if you can't reproduce the issue in the debugger, you can add a trace before re-throwing the new exception (with the good old System.out.println at worse, with a good log system like log4j otherwise).

如上所述......
我想补充一点,如果您无法看到正在发生的事情,如果您无法在调试器中重现该问题,您可以在重新抛出新异常之前添加跟踪(使用旧系统.out.println 更糟,否则使用像 log4j 这样的良好日志系统)。

回答by Tom Hawtin - tackline

No. It's very easy to check.

不,这很容易检查。

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");
        }
    }
}

Should print:

应该打印:

In catch IOException: class java.io.IOException
In finally
Exception in thread "main" java.lang.RuntimeException
        at Catch.main(Catch.java:8)

Technically that could have been a compiler bug, implementation dependent, unspecified behaviour, or something. However, the JLS is pretty well nailed down and the compilers are good enough for this sort of simple thing (generics corner case may be a different matter).

从技术上讲,这可能是编译器错误、依赖于实现、未指定的行为或其他原因。但是,JLS 已经很好地确定下来了,并且编译器对于这种简单的事情来说已经足够好了(泛型极端情况可能是另一回事)。

Also note, if you swap around the two catch blocks, it wont compile. The second catch would be completely unreachable.

另请注意,如果您交换两个 catch 块,它将无法编译。第二个捕获将是完全无法到达的。

Note the finally block always runs even if a catch block is executed (other than silly cases, such as infinite loops, attaching through the tools interface and killing the thread, rewriting bytecode, etc.).

请注意,即使执行了 catch 块, finally 块也始终运行(除了愚蠢的情况,例如无限循环、通过工具接口附加并杀死线程、重写字节码等)。

回答by Vinko Vrsalovic

It won't be caught by the second catch block. Each Exception is caught only when inside a try block. You can nest tries though (not that it's a good idea generally):

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

try {
    doSomething();
} catch (IOException) {
   try {
       doSomething();
   } catch (IOException e) {
       throw new ApplicationException("Failed twice at doSomething" +
       e.toString());
   }          
} catch (Exception e) {
}

回答by Uri

No, since the catches all refer to the same try block, so throwing from within a catch block would be caught by an enclosing try block (probably in the method that called this one)

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

回答by Alex Miller

The Java Language Specification says in section 14.19.1:

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

If execution of the try block completes abruptly because of a throw of a value V, then there is a choice:

  • If the run-time type of V is assignable to the Parameter of any catch clause of the try statement, then the first (leftmost) such catch clause is selected. The value V is assigned to the parameter of the selected catch clause, and the Block of that catch clause is executed. If that block completes normally, then the try statement completes normally; if that block completes abruptly for any reason, then the try statement completes abruptly for the same reason.

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

  • 如果 V 的运行时类型可分配给 try 语句的任何 catch 子句的参数,则选择第一个(最左边的)此类 catch 子句。将值 V 分配给所选 catch 子句的参数,并执行该 catch 子句的 Block。如果该块正常完成,则 try 语句正常完成;如果该块因任何原因突然完成,则 try 语句因相同原因突然完成。

Reference: http://java.sun.com/docs/books/jls/second_edition/html/statements.doc.html#24134

参考:http: //java.sun.com/docs/books/jls/second_edition/html/statements.doc.html#24134

In other words, the first enclosing catch that can handle the exception does, and if an exception is thrown out of that catch, that's not in the scope of any other catch for the original try, so they will not try to handle it.

换句话说,第一个可以处理异常的封闭 catch 可以处理,并且如果异常从该 catch 中抛出,那么对于原始 try 而言,它不在任何其他 catch 的范围内,因此它们不会尝试处理它。

One related and confusing thing to know is that in a try-[catch]-finally structure, a finally block may throw an exception and if so, any exception thrown by the try or catch block is lost. That can be confusing the first time you see it.

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

回答by Mastergeek

If you want to throw an exception from the catch block you must inform your method/class/etc. that it needs to throw said exception. Like so:

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

public void doStuff() throws MyException {
    try {
        //Stuff
    } catch(StuffException e) {
        throw new MyException();
    }
}

And now your compiler will not yell at you :)

现在你的编译器不会对你大喊大叫了 :)

回答by Ted K

Old post but "e" variable must be unique:

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

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