简体   繁体   English

如何突破初始化块?

[英]How to break out initialization block?

I have a class looks like this 我上课看起来像这样

class Some {

    private enum Inner {
    }
}

And I'm trying to find the Inner class in a initialization block of my test class. 我正在尝试在测试类的初始化块中找到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");
    }
}

The compiler doesn't like this and I couldn't find any better way. 编译器不喜欢这样,我找不到更好的方法。

How can I solve this? 我该如何解决? Is there any good pattern for this? 有什么好的模式吗?

static and instance initialization block cannot throw checked exceptions as there is no way to declare that those blocks throws these execeptions. staticinstance初始化块无法引发检查的异常,因为无法声明这些块引发了这些异常。 Change ExceptionInitializerError to RuntimeException (or any subclass) and wrap your code in try-catch ExceptionInitializerError更改为RuntimeException (或任何子类),然后将代码包装在try-catch

Besides here, you are not returning nor breaking thus you always throw exception. 除了这里,您不会返回也不会中断,因此您总是会抛出异常。

As for "breaking out" well simply yo dont. 至于“爆发”好吧,你不要。 You have to write that block as it would be body of void method but with the restriction that you cannot use return anywhere. 您必须编写该块,因为它会成为void方法的主体,但有一个限制,即您不能在任何地方使用return

There are a few problems with your code: 您的代码存在一些问题:

  1. You have the exception name incorrect. 您的异常名称不正确。 The exception you are trying to throw is called ExceptionInInitializerError not ExceptionInitializerError . 您尝试引发的ExceptionInInitializerError称为ExceptionInInitializerError而不是ExceptionInitializerError That is one reason why it won't compile. 这就是为什么它无法编译的原因之一。

  2. Never 1 throw Error or subclasses of Error . 从不1Error或子类Error

  3. If you need to throw an unchecked exception, throw RuntimeException . 如果需要抛出未经检查的异常,则抛出RuntimeException Or better still, pick something more specific or define and use your own custom (unchecked) exception class. 还是更好,选择一些更具体的东西,或者定义并使用您自己的自定义(未经检查)异常类。

  4. This should (probably) be a static initializer block, not a plain (instance) initializer. 这(可能)应该是static初始化程序块,而不是普通的(实例)初始化程序。 You want this code to be executed once ... not every time a SomeTest instance is created. 您希望此代码一次执行,而不是每次创建SomeTest实例时都执行一次

  5. Bailing out of a static initializer block is something you want to avoid. 要避免从static初始值设定项块中释放出来。 It basically leaves you with a dead application ... because the enclosing class and any classes that depend on it become uninitializable. 从根本上来说,这会让您的应用程序失效……因为封闭的类以及依赖于该类的任何类都无法初始化。


Having said that, the following might be a more appropriate structure: 话虽如此,以下可能是一个更合适的结构:

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

Note that we need to do the final assignment to FINAL_VAR in a way that ensures that it is definitely assigned. 请注意,我们需要以确保已明确分配的方式对FINAL_VAR进行最终分配。 (My guess is that is a second reason you were getting compilation errors.) (我的猜测是这是您遇到编译错误的第二个原因。)

And a more natural way to write the above would be: 编写上面内容的更自然的方法是:

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

1 - Maybe a bit too strong. 1-可能太强了。 I would say that throwing AssertionError is OK ... assuming that you intend for it never be caught / recovered from. 我要说的是,抛出AssertionError是可以的...假设您从未打算将其捕获/恢复。 In this case, recovery is moot anyway. 在这种情况下,无论如何都没有恢复的余地。

There are couple of issues: 有几个问题:

  1. The exception is always thrown 总是抛出异常
  2. You are assigning to a final variable in a loop 您正在循环中分配给最终变量
  3. The initialization block is not static and assigning to a static final variable 初始化块不是静态的,而是分配给静态的最终变量

Check this out: 看一下这个:

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");
    }
}

Use intermediate variable before final assignment. 在最终分配之前使用中间变量。

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;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM