在catch子句中抛出exception

我有两段代码:

class PreciseRethrow { public static void main(String[] str) { try { foo(); } catch (NumberFormatException ife) { System.out.println(ife); } } static private void foo() throws NumberFormatException { try { int i = Integer.parseInt("ten"); } catch (Exception e) { throw e; } } } 

并且:

 class PreciseRethrow { public static void main(String[] str) { try { foo(); } catch (NumberFormatException ife) { System.out.println(ife); } } static private void foo() throws NumberFormatException { try { int i = Integer.parseInt("ten"); } catch (Exception e) { throw new Exception(); } } } 

在第二种情况下,当我在catch子句中抛出新的Exception()时,我得到了编译错误“Unhandled exception type Exception”。 你能解释一下我为什么在第一种情况下一切都好,但在第二种情况下我得到编译错误? 在这两种情况下我都抛出exception,但在第二种情况下,我创建了exception的新实例(这只是两个例子中的区别)。 感谢帮助。

首先: 您的第一个示例也不使用Java 6进行编译 。 然而,由于exception处理中的新function, 它将使用Java 7进行编译。

有关更多信息,请参阅此链接 。 基本上,从Java 7开始,编译器可以更精确地分析从try块抛出的exception; 即使你捕获一个或多个抛出exception的超类并按“原样”重新抛出它(即没有强制转换),编译器也不会抱怨。 然而,Java 6及更早版本抱怨。

在第二个示例中,您将重新抛出一个Exception实例。 事实上,这与签名不符。

总而言之,这意味着使用Java 7,您可以这样做,但不能使用Java 6:

 public void someMethod() throws MyException { try { throw new MyException(); } catch (Exception e) { // Note: Exception, not MyException throw e; } } 

Java 6只看到catch参数的类型为Exception ; 对于Java 6,这与方法签名 – >编译错误不匹配。

Java 7发现try块只能抛出MyException 。 因此方法签名匹配 – >没有编译错误。

但是不要这样做;)这很令人困惑……

区别在于编译器可以看到在第一个示例中可以重新抛出的唯一已检查exception是NumberFormatException 。 (您没有创建任何新的exception。)因此,它很高兴在标头中throws NumberFormatException {声明。

但是,在第二个示例中,您显式抛出了未在标头中声明的已检查exception,因此可以预见您会收到编译器错误。

在第一个代码片段中,您将重新抛出可能出现的NumberFormatException 。 在第二个代码片段中,您只抛出一般的Exception ,这不是NumberFormatException ,正如方法声明的那样。

您正在尝试抛出exception,但是您声明将抛出NumberFormatException ,这是Exception的子类型。 所有NumberFormatException都是Exception ,但并非所有Exception都是NumberFormatException ,因此不允许。 但是,在第一个示例中,尽管您正在捕获Exception ,但编译器和IDE知道它只会是一个NumberFormatException ,这是安全的。

编译器可以在throw e的情况下确定它只能是已经在throws子句中声明的NumberFormatException类型的已检查exception。

在后一种情况下,您尝试抛出已检查的Exception ,该Exception需要在throws子句中声明或捕获。

在这里,你从catch块抛出新的Exception(),但是你提到了你的方法foo()只能抛出NumberFormatException(),它在层次结构中较低

  static private void foo() throws NumberFormatException { try { int i = Integer.parseInt("ten"); } catch (Exception e) { throw new Exception(); } } 

在这两种情况下,编译时错误都会出现。因为您尝试抛出一个名为Exception的已检查exception。 你必须做两件事之一:

在catch块中使用try构造或在foo()的throws子句中添加Exception