这种行为似乎只发生在 Java 1.7 上。使用 1.6 编译时,我收到以下编译器错误消息:
c:\dev\src\misc>javac -source 1.6 Main.java
warning: [options] bootstrap class path not set in conjunction with -source 1.6
Main.java:22: error: unreported exception Exception; must be caught or declared
to be thrown
throw e;
^
1 error
1 warning
但是对于 Java 1.7,它可以编译。
c:\dev\src\misc>javac -source 1.7 Main.java
c:\dev\src\misc>
...直到我在try 块中实际抛出Exception:
public static void throwsOrNotThrowsThatsTheQuestion() {
try {
// Any processing
throw new IOException("Fake!");
} catch (Exception e) {
throw e;
}
正在编译...
c:\dev\src\misc>javac -source 1.7 Main.java
Main.java:22: error: unreported exception IOException; must be caught or declare
d to be thrown
throw e;
^
1 error
看起来 Java 1.7 变得足够聪明,可以通过分析 try 块代码来检测可能抛出的 Exception(s) 类型,而 1.6 刚刚看到 Exception 类型的 throw e; 并给出一个错误。
将其更改为抛出 RuntimeException 使其按预期编译,因为与往常一样,未选中的 Exceptions 不需要 throws 子句:
public static void throwsOrNotThrowsThatsTheQuestion() {
try {
// Any processing
throw new RuntimeException("Fake!");
} catch (Exception e) {
throw e;
}
正在编译...
c:\dev\src\misc>javac -source 1.7 Main.java
c:\dev\src\misc>
解释
这是怎么回事:
Java 7 引入了more inclusive type checking。引用...
考虑以下示例:
static class FirstException extends Exception { }
static class SecondException extends Exception { }
public void rethrowException(String exceptionName) throws Exception {
try {
if (exceptionName.equals("First")) {
throw new FirstException();
} else {
throw new SecondException();
}
} catch (Exception e) {
throw e;
}
}
此示例的 try 块可能会抛出 FirstException 或 SecondException。假设您要在 rethrowException 方法声明的 throws 子句中指定这些异常类型。在 Java SE 7 之前的版本中,您不能这样做。因为catch子句的异常参数e是Exception类型,而catch块重新抛出异常参数e,所以只能在rethrowException方法声明的throws子句中指定异常类型Exception。
但是,在 Java SE 7 中,您可以在 rethrowException 方法声明的 throws 子句中指定异常类型 FirstException 和 SecondException。 Java SE 7 编译器可以确定语句 throw e 抛出的异常一定来自 try 块,而 try 块抛出的异常只能是 FirstException 和 SecondException。即使 catch 子句的异常参数 e 是 Exception 类型,编译器也可以确定它是 FirstException 或 SecondException 的实例:
(强调我的)
public void rethrowException(String exceptionName)
throws FirstException, SecondException {
try {
// ...
}
catch (Exception e) {
throw e;
}
}