代码之家  ›  专栏  ›  技术社区  ›  Jin Kwon

如何突破初始化块?

  •  0
  • Jin Kwon  · 技术社区  · 7 年前

    我有一节课看起来像这样

    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 回复  |  直到 7 年前
        1
  •  3
  •   Antoniossss    7 年前

    static 和 instance 初始化块不能抛出选中的异常,因为无法声明这些块抛出这些异常。改变 ExceptionInitializerError 到 RuntimeException (或任何子类)并用 try-catch

    除此之外,你不会返回也不会破坏,因此你总是抛出异常。

    至于“突围”,那你就别想了。你必须把那块写下来,因为它是 void 方法,但有不能使用的限制 return 在任何地方

        2
  •  3
  •   Stephen C    7 年前

    你的代码有几个问题:

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

    2. 从不 1. 投 Error 或其子类 错误 .

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

    4. 这应该(可能)是一个好消息 static 初始值设定项块,而不是普通(实例)初始值设定项。你想执行这段代码吗 一旦 ... 不是每次 SomeTest 实例被创建。

    5. 摆脱困境 静止的 初始值设定项阻塞是您想要避免的。它基本上给你留下了一个死气沉沉的应用程序。。。因为封闭类和依赖它的任何类都变得不可初始化。


    话虽如此,下面 可以 成为一个更合适的结构:

     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 可以。。。假设你 打算 因为它永远不会被发现。在这种情况下,复苏是毫无意义的。

        3
  •  0
  •   Alex    7 年前

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

    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;
        }
    }
    
        4
  •  0
  •   Dakshinamurthy Karra    7 年前

    有两个问题:

    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");
        }
    }
    
    推荐文章