0

我有一堂课看起来像这样

class Some {

    private enum Inner {
    }
}

我正在尝试Inner在我的测试类的初始化块中找到该类。

class SomeTest {

    private static final Class<?> INNER_CLASS;

    {
        for (final Class<?> declaredClass: Some.class.getDeclaredClasses()) {
            if (declaredClass.getSimpleName().equals("Inner")) {
                INNER_CLASS = declaredClass;
                // Variable `INNER_CLASS` might be assigned in loop
                // break? return?
            }
        }
        throw new ExceptionInitializerError("failed to find Inner.class");
    }
}

编译器不喜欢这样,我找不到更好的方法。

我该如何解决这个问题?这有什么好的模式吗?

4

4 回答 4

3

static并且instance初始化块不能抛出已检查的异常,因为无法声明这些块会抛出这些异常。更改ExceptionInitializerErrorRuntimeException(或任何子类)并将您的代码包装在try-catch

除此之外,你没有返回也没有打破,因此你总是抛出异常。

至于“爆发”很好,你不知道。您必须编写该块,因为它是void方法的主体,但有您不能return在任何地方使用的限制。

于 2019-01-29T07:55:31.800 回答
3

您的代码存在一些问题:

  1. 您的异常名称不正确。您尝试抛出的异常称为ExceptionInInitializerErrornot ExceptionInitializerError。这就是它无法编译的原因之一。

  2. 永远不要1 throwErrorError.

  3. 如果您需要抛出未经检查的异常,请抛出RuntimeException. 或者更好的是,选择更具体的东西或定义并使用您自己的自定义(未经检查的)异常类。

  4. 这应该(可能)是一个static初始化程序块,而不是一个普通的(实例)初始化程序。您希望此代码执行一次……而不是每次SomeTest创建实例时。

  5. 摆脱static初始化程序块是您想要避免的事情。它基本上给你留下了一个死的应用程序......因为封闭类和任何依赖它的类都变得不可初始化。


话虽如此,以下可能是更合适的结构:

 static {
     BlahType tmp = null;
     label: {
         for (...) {
             if (...) {
                 tmp = ...;
                 break label;
             }
         }
         throw new SomeException(...);
     }
     FINAL_VAR = tmp;
}

请注意,我们需要以FINAL_VAR确保它被明确分配的方式进行最终分配。(我的猜测是这是您遇到编译错误的第二个原因。)

编写上述内容的更自然的方式是:

static {
     BlahType tmp = null;
     for (...) {
         if (...) {
             tmp = ...;
             break;
         }
     }
     if (tmp == null) {
         throw new SomeException(...);
     }
     FINAL_VAR = tmp;
}

1 - 可能有点太强了。我会说投掷AssertionError是可以的......假设你打算永远不会被抓住/恢复。在这种情况下,无论如何恢复都是没有意义的。

于 2019-01-29T08:02:41.997 回答
0

有几个问题:

  1. 总是抛出异常
  2. 您正在循环中分配给最终变量
  3. 初始化块不是静态的并分配给静态最终变量

看一下这个:

class SomeTest {

    private static final Class<?> INNER_CLASS;

    static {
        Class<?> foundClass = null;
        for (final Class<?> declaredClass : Some.class.getDeclaredClasses()) {
            if (declaredClass.getSimpleName().equals("Inner")) {
                foundClass = declaredClass;
                // Variable `INNER_CLASS` might be assigned in loop
                // break? return?
            }
        }
        INNER_CLASS = foundClass;
        // throw new Exception("failed to find Inner.class");
    }
}
于 2019-01-29T07:56:46.283 回答
0

在最终赋值之前使用中间变量。

class SomeTest {

    private static final Class<?> INNER_CLASS;
    static {
        Class<?> innerClass = null;
        for (final Class<?> declaredClass: Some.class.getDeclaredClasses()) {
            if (declaredClass.getSimpleName().equals("Inner")) {
                innerClass = declaredClass;
            }
        }
        if (innerClass == null) {
            throw new ExceptionInitializerError("failed to find Inner.class");
        }
        INNER_CLASS = innerClass;
    }
}
于 2019-01-29T07:57:11.897 回答