Java 如何突破初始化块?

Java 如何突破初始化块?,java,initialization-block,Java,Initialization Block,我有一节课看起来像这样 class Some { private enum Inner { } } 我试图在测试类的初始化块中找到内部类 class SomeTest { private static final Class<?> INNER_CLASS; { for (final Class<?> declaredClass: Some.class.getDeclaredClasses()) {

我有一节课看起来像这样

class Some {

    private enum 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");
    }
}
类测试{
私有静态final类内部_类;
{
for(最终类declaredClass:Some.Class.getDeclaredClass()){
if(declaredClass.getSimpleName().equals(“内部”)){
内部类=申报类;
//变量'internal_CLASS'可能在循环中赋值
//休息?回来?
}
}
抛出新的ExceptionInitializeError(“未能找到内部.class”);
}
}
编译器不喜欢这样,我找不到更好的方法


我怎样才能解决这个问题?有什么好的模式吗?

静态
实例
初始化块不能抛出选中的异常,因为无法声明这些块抛出这些异常。将
exceptioninitializeerror
更改为
RuntimeException
(或任何子类),并将代码包装到
try catch

除此之外,您不会返回也不会中断,因此您总是抛出异常


至于“爆发”,那你就别想了。您必须编写该块,因为它是
void
方法的主体,但有一个限制,即您不能在任何地方使用
return

有两个问题:

  • 异常总是被抛出
  • 您正在为循环中的最后一个变量赋值
  • 初始化块不是静态的,并分配给静态最终变量
  • 看看这个:

    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");
        }
    }
    
    类测试{
    私有静态final类内部_类;
    静止的{
    类foundClass=null;
    for(最终类declaredClass:Some.Class.getDeclaredClass()){
    if(declaredClass.getSimpleName().equals(“内部”)){
    foundClass=declaredClass;
    //变量'internal_CLASS'可能在循环中赋值
    //休息?回来?
    }
    }
    内部_类=foundClass;
    //抛出新异常(“未能找到内部.class”);
    }
    }
    
    在最终赋值之前使用中间变量

    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;
        }
    }
    
    类测试{
    私有静态final类内部_类;
    静止的{
    类innerClass=null;
    for(最终类declaredClass:Some.Class.getDeclaredClass()){
    if(declaredClass.getSimpleName().equals(“内部”)){
    innerClass=declaredClass;
    }
    }
    if(innerClass==null){
    抛出新的ExceptionInitializeError(“未能找到内部.class”);
    }
    内部类=内部类;
    }
    }
    
    您的代码有几个问题:

  • 您的异常名称不正确。您试图抛出的异常称为
    exceptionininitializerror
    而不是
    exceptioninitializerror
    。这就是它无法编译的原因之一

  • 从不抛出
    错误
    错误
    的子类

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

  • 这应该(可能)是一个
    静态
    初始值设定项块,而不是一个普通的(实例)初始值设定项。您希望此代码执行一次。。。并非每次创建
    SomeTest
    实例时

  • 退出
    静态
    初始值设定项块是您希望避免的事情。它基本上给你留下了一个死气沉沉的应用程序。。。因为封闭类和依赖它的任何类都变得不可初始化


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

     static {
         BlahType tmp = null;
         label: {
             for (...) {
                 if (...) {
                     tmp = ...;
                     break label;
                 }
             }
             throw new SomeException(...);
         }
         FINAL_VAR = tmp;
    }
    
    请注意,我们需要对
    final\u VAR
    进行最终赋值,以确保它被明确赋值。(我猜这是您出现编译错误的第二个原因。)

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

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


    1-可能有点太强了。我想说抛出断言错误是可以的。。。假设你的意图是永远不会被抓住/找回。在这种情况下,恢复是没有意义的。

    编译器对此有什么不喜欢的?我没有看到return语句,这意味着您的
    ExceptionInitializeError
    将始终被抛出。它不应该是静态初始值设定项块吗?初始化块不是静态的,并且分配给一个语义有效的静态变量。分配给final在非静态块中无效。但需要检查。最后的变量是不同的故事。只需澄清第3点,即您所谈论的是静态最终结果。