在Java中,抛出已检查的异常的方法(Exception或其子类型 - IOException,InterruptedException等)必须声明throws语句:
实际上不是这样的。有点好笑:编译器知道 e 不是一个受检异常,因此允许重新抛出它。事情甚至有点荒谬,这段代码无法编译:
第一个片段是一个问题的动机。
编译器知道受检异常不能在安全方法中抛出 - 那么它是否应该允许仅捕获未检查的异常?
public abstract int read() throws IOException;
没有声明 throws
语句的方法不能抛出已检查的异常。
public int read() { // does not compile
throw new IOException();
}
// Error: unreported exception java.io.IOException; must be caught or declared to be thrown
但在Java中,在安全方法中捕获已检查的异常仍然是合法的:
public void safeMethod() { System.out.println("I'm safe"); }
public void test() { // method guarantees not to throw checked exceptions
try {
safeMethod();
} catch (Exception e) { // catching checked exception java.lang.Exception
throw e; // so I can throw... a checked Exception?
}
}
实际上不是这样的。有点好笑:编译器知道 e 不是一个受检异常,因此允许重新抛出它。事情甚至有点荒谬,这段代码无法编译:
public void test() { // guarantees not to throw checked exceptions
try {
safeMethod();
} catch (Exception e) {
throw (Exception) e; // seriously?
}
}
// Error: unreported exception java.lang.Exception; must be caught or declared to be thrown
第一个片段是一个问题的动机。
编译器知道受检异常不能在安全方法中抛出 - 那么它是否应该允许仅捕获未检查的异常?
回到主要问题 - 实现这种方式捕获已检查异常的原因是什么?这只是设计上的缺陷还是我忽略了一些重要因素 - 也许是向后不兼容性?如果在此情况下仅允许捕获 RuntimeException
,可能会出现什么问题?举例说明将更有助于理解。
final Object ob = "foo";
也应该导致编译器错误,因为我们在编译时知道ob的运行时类型将是String。 - biziclopsafeMethod()
是安全的,这意味着捕获的Exception e
必须是RuntimeException
。如果保持不变(如第一个片段中所示),则一切都很好。但是,在第二个片段中显式转换为Exception
时,您使编译器忘记了它所知道的,并相信它可能是任何Exception
,这当然是不可以的。 - Erick G. Hagstrom