【问题标题】:Why can't I catch the exception more than one time?为什么我不能多次捕获异常?
【发布时间】:2014-11-24 19:18:47
【问题描述】:

JLS 8, 14.20:

try 语句执行一个块。如果抛出一个值并且尝试 语句有一个或多个可以捕获它的 catch 子句,然后 控制将转移到第一个这样的catch子句

看起来我可能有两个用于相同异常类型的 catch 子句。但是当我尝试这个时,我会收到编译时错误。

public static void main (String[] args) throws java.lang.Exception
{
    try{
    } catch(RuntimeException ioe){
    } catch(NumberFormatException e){ //Already caught
    } 
}

IDEONE

你能用 JLS 解释一下吗?

【问题讨论】:

  • 你可能有两个,但It is a compile-time error if a union of types contains two alternatives Di and Dj (i ≠ j) where Di is a subtype of Dj (§4.10.2).。如果必须,请放置一个 try-catch(NFE) 并重新抛出它,然后在其周围放置一个 try-catch(RE)
  • 在同一个 try 语句中多次捕获同一个异常有什么意义? unreachable catch block ... 上的编译错误非常明显。
  • @Philipp 我这里有联合类型吗?
  • JLS 11.2.3: 如果 catch 子句可以捕获异常类 E1 并且紧接的 try 语句的前面的 catch 子句可以捕获 E1 或E1.
  • 最后,报价正是我想要的。 @Seelenvirtuose 谢谢。

标签: java exception language-lawyer


【解决方案1】:

因为 RunTimeException 是 NumberFormatException 的基类。 http://docs.oracle.com/javase/7/docs/api/java/lang/NumberFormatException.html

【讨论】:

  • 是的,我知道。我问为什么我们不能两次或多次捕获相同的异常?
  • 这是因为它在规范中说“第一个”catch 子句。
【解决方案2】:

您从捕获的异常的层次结构中得到的编译器错误。

NumberFormatException extends IllegalArgumentException extends RuntimeException

将 catch 块视为安全网。 NumberFormatException 网络非常小,因为它是更高层次异常的特例。 RuntimeException 网络是可能的最大网络之一,并且会捕获此级别上的任何内容(除了 Exception 和 Throwables,它们是“优越的”)。您所做的是将小网放在大网下方。所以编译器足够礼貌地给你提示,小网永远不会到达。

(我知道这个比喻不是 100% 准确的,但在这种情况下可以正常工作。)

如果您先捕获 NumberFormatException 然后再捕获 RuntimeException,编译器会欣然同意! :-) 您还可以从第一个块中重新抛出捕获的异常。

【讨论】:

    【解决方案3】:

    NumberFormatException 是 RuntimeException 的一个特例,因此您的 NumberFormatException 已经被第一条语句捕获。但是,您可以切换这两个 catch 子句的顺序;但请记住,只会执行一个:

    • NumberFormatException 子句(如果异常具有这种类型)
    • 所有其他类型的 RuntimeException 的 RuntimeException 子句

    至于为什么是这样的……嗯,这就是语言的设计方式。如果所有匹配的 catch 块都被执行了,那么正确处理错误将变得更加困难。

    【讨论】:

    • 这就是语言的设计方式你能提供它证明的引文吗?语言设计必须在规范中完整描述,对吧?
    • 您在问题中引用的规范部分正是这样说的:执行第一个匹配异常的catch 子句,这意味着只执行一个匹配的catch 子句。至于说明为什么不能按照问题中显示的顺序编写 catch 子句的规范,这是一个不同的问题(可能写在其他地方)
    • docs.oracle.com/javase/specs/jls/se8/html/…: "如果 catch 子句可以捕获异常类 E1,并且紧接在其内的 try 语句的前面的 catch 子句可以捕获 E1 或 E1 的超类,则这是编译时错误。 "编辑:注意到它是由 Seelenvirtuose 之前发布的,作为对您问题的评论
    【解决方案4】:

    NumberFormatExceptionRuntimeException 的子类型当你捕获RuntimeException 时,它将捕获所有类型的RuntimeException,包括NumberFormatException。这就是为什么它说已经被抓住了。

    【讨论】:

      猜你喜欢
      • 2021-03-16
      • 1970-01-01
      • 2012-12-06
      • 2010-12-07
      • 1970-01-01
      • 1970-01-01
      • 2012-08-27
      • 2013-10-26
      • 2021-05-13
      相关资源
      最近更新 更多