在catch子句中抛出异常

7

我有两段代码:

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子句中抛出新的异常(new Exception())时,我得到了编译错误“Unhandled exception type Exception”。您能解释一下为什么第一种情况一切正常,但第二种情况却出现了编译错误吗?在两种情况下,我都抛出了异常,但在第二种情况下,我创建了一个新的异常实例(这是这两个示例之间唯一的区别)。感谢您的帮助。

@prash:你是不是忘记投票了? - Keppil
是的!事实上我是用手机完成的。但请求还未完成。3G很慢。现在完成了。谢谢。@Keppil - spiderman
7个回答

7
首先:您的第一个示例在Java 6中也无法编译。但是由于异常处理中的新特性,它可以在Java 7中编译。
请参阅此链接以获取更多信息。基本上,从Java 7开始,编译器可以更精确地分析从try块抛出的异常;即使您捕获了一个或多个抛出异常的超类并将其“原样”重新抛出(即不使用强制转换),编译器也不会抱怨。然而,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。因此,方法签名匹配-->没有编译错误。

但不要这样做;) 这会令人困惑...


讲解得非常清晰,特别是总结部分。 - spiderman

2

区别在于编译器可以看到第一个示例中唯一可能重新抛出的已检查异常是 NumberFormatException。(您没有创建任何新异常。)因此,它对头文件中的 throws NumberFormatException { 声明感到满意。

然而,在第二个示例中,您明确抛出了一个未在头文件中声明的已检查异常,因此可以预见地会出现编译器错误。


我在阅读@fge的文章后才明白Java6和Java7之间的区别。但很好。 - spiderman

0
在这里,你从catch块中抛出了new Exception(),但是你已经声明你的方法foo()只能抛出层级较低的NumberFormatException()。
   static private void foo() throws NumberFormatException {
    try {
    int i = Integer.parseInt("ten");
   } catch (Exception e) {
    throw new Exception();
   }
  }

0
在第一个代码片段中,您正在重新抛出可能出现的NumberFormatException。在第二个代码片段中,您正在抛出通用的异常Exception,而不是作为方法声明的NumberFormatException。

0

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


0
编译器可以确定在throw e的情况下,它只能是已在throws子句中声明的类型为NumberFormatException的已检查异常。
在后一种情况下,您正在尝试抛出需要在throws子句中声明或捕获的已检查Exception

0
在这两种情况下,都会出现编译时错误。因为你试图抛出一个叫做 Exception 的已检查异常。
你需要做以下两件事之一:
1. 在 catch 块中使用 try 结构 2. 或者将 Exception 添加到 foo() 的 throws 子句中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接