这是一个描述我的问题的简化类:
public class Main {
enum Test{
First(method()){ // Unhandled exception type Exception
// ...
};
Test(Object obj){
//...
}
}
static Object method() throws Exception{
// ...
if (someCondition){
throw new Exception();
}
}
}
以上someCondition
取决于设备和某些情况,我现在无法决定,也如您所见,我不想捕获 Exception
在method
.
最佳答案
是的。这是一个编译错误。
没有。没有特殊的语法来处理这个问题。
I do not want to catch Exception in method.
不幸的是,如果您抛出一个已检查的异常,它必须在调用堆栈的更上方被捕获。这是 Java 语言的一项基本设计原则,也是编译器严格执行的原则。
在这种情况下,无法捕获已检查的异常。因此,如果您要调用枚举常量参数中的方法(根据您的代码),该方法不能抛出已检查的异常1。
这是一个可能的解决方法,尽管这可能是一个坏主意:
public class Main {
enum Test{
First(methodCatchingException()){
// ...
};
Test(Object obj){
//...
}
}
static Object method() throws Exception{
// ...
if (someCondition){
throw new Exception();
}
}
static Object methodCatchingException() {
try {
return method();
} catch (Exception ex) {
throw new SomeRuntimeException("the sky is falling!", ex);
}
}
}
看待这个问题的另一种方法是问自己,如果编译器允许你这样写......并且抛出了异常,那么异常应该发生什么?它会去哪里?
- 您无法捕获它...因为
enum
初始化类似于static
初始化。 - 如果 Java 运行时完全忽略抛出的异常,那就太糟糕了。
- 如果 Java 运行时崩溃,则已检查异常的模型就会被破坏。
所以,这对我来说是 Java 语言设计是正确的,Java 编译器是正确的......这里真正的问题在于您的应用程序设计:
您不应该在此处传播已检查的异常。如果在此上下文中发生异常,那么它绝对不是可恢复的错误。
也许不建议为此使用枚举......因为可能会出现不可恢复的初始化错误。
(请注意,如果此方法调用因未经检查的异常而终止,则会将其转变为 ExceptionInInitializerError 。此外,JVM 会将 enum
类标记为不可初始化,如果您的应用程序尝试使用它,则会抛出 NoClassDefFoundError
;例如,通过 Class.forName(...)
。)
我假设此处使用Exception
用于说明目的。将方法声明为 throws Exception
或 throw new Exception(...)
1 - 我查看了 JLS,寻找支持这一点的东西。据我所知,规范中没有提到这种情况。我本来希望看到它列在 JLS 11.2.3 中。但是,很明显,编译器不能允许检查异常在此时传播,因为这会“破坏”检查异常工作的模型。
关于java - 未处理的异常类型 Exception,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31095326/