如何突破初始化块?

时间:2019-01-29 07:50:43

标签: java initialization-block

我有一个看起来像这样的班

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 个答案:

答案 0 :(得分:3)

staticinstance初始化块无法引发已检查的异常,因为无法声明这些块引发了这些异常。将ExceptionInitializerError更改为RuntimeException(或任何子类),然后将代码包装在try-catch

除了这里,您不会返回也不会中断,因此您总是会抛出异常。

至于“爆发”就好了,不要。您必须像编写void方法的主体一样编写该块,但要限制您不能在任何地方使用return

答案 1 :(得分:3)

您的代码存在一些问题:

  1. 您的异常名称不正确。您尝试引发的异常称为ExceptionInInitializerError而不是ExceptionInitializerError。这是它不能编译的一个原因。

  2. 从不 1 抛出ErrorError的子类。

  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是可以的……假设您打算永远不会被捕获/恢复。在这种情况下,恢复仍然毫无意义。

答案 2 :(得分: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");
    }
}

答案 3 :(得分: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;
    }
}