在catch子句中抛出异常

时间:2014-04-13 10:27:45

标签: java exception-handling

我有两段代码:

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”。你能解释一下我为什么在第一种情况下一切都好,但在第二种情况下我得到编译错误?在这两种情况下我都抛出异常,但在第二种情况下,我创建了异常的新实例(这只是两个例子中的区别)。谢谢你的帮助。

7 个答案:

答案 0 :(得分:6)

首先:你的第一个例子不能用Java 6编译。然而,由于异常处理中的新功能, 将使用Java 7进行编译。

有关详细信息,请参阅this link。基本上,从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。因此,方法签名匹配 - >没有编译错误。

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

答案 1 :(得分:2)

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

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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

在后一种情况下,你试图抛出需要在throws子句中声明或被捕获的已检查Exception

答案 5 :(得分:0)

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

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

答案 6 :(得分:0)

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

在catch块中使用try构造 要么  在foo()

的throws子句中添加Exception