未处理的异常类型异常

时间:2015-06-28 01:39:58

标签: java exception enums

这是一个描述我的问题的简化类:

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。< / p>

2 个答案:

答案 0 :(得分:2)

是。这是一个编译错误。

没有。没有特殊的语法来处理这个问题。

  

我不想在方法中捕获异常。

不幸的是,如果您抛出一个已检查的异常,必须在调用堆栈中进一步捕获。这是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编译器是正确的......这里的真正问题在于你的应用程序 design

  • 您不应在此处传播已检查的例外。如果在此上下文中发生异常,则绝对不是可恢复的错误。

  • 也许不建议使用枚举...因为可能出现不可恢复的初始化错误。

(请注意,如果此方法调用因未经检查的异常而终止,则会将其转换为ExceptionInInitializerError。此外,JVM会将enum类标记为无法初始化,并将抛出NoClassDefFoundError如果您的应用尝试使用它;例如通过Class.forName(...)。)

我假设此处使用Exception作为说明目的。将方法声明为throws Exceptionthrow new Exception(...)

是一件坏事

1 - 我看了一下JLS有什么要支持的。据我所知,该规范没有提到这种情况。我预计会在JLS 11.2.3中看到它列出来。但是,很明显,编译器不能允许已检查的异常在该点传播,因为它会&#34; break&#34;检查异常如何工作的模型。

答案 1 :(得分:1)

我认为你不想在这里抛出一个检查过的异常(这就是Exception)。原因是:您在method的构造函数内调用了Test。真的没有一个干净的方法来处理它。

虽然这里显而易见的选择是切换到RuntimeException,但我希望您首先重新考虑抛出异常。由于你的枚举只会在其中声明First,它真的是否有意义在它被实例化时抛出异常?我个人认为不是这样;任何危险的操作都应该推迟到你想要调用它,然后那么你想要抛出异常。