简体   繁体   English

Java - 最终变量可以在静态初始化块中初始化吗?

[英]Java - Can final variables be initialized in static initialization block?

Based on my understanding of the Java language, static variables can be initialized in static initialization block . 根据我对Java语言的理解,静态变量可以在static initialization blockstatic initialization block

However, when I try to implement this in practice ( static variables that are final too), I get the error shown in the screenshot below: 但是,当我尝试在实践中实现它时( static变量也是final ),我得到下面屏幕截图中显示的错误:

https://i.stack.imgur.com/5I0am.jpg

Yes of course: static final variables can be initialized in a static block but .... you have implicit GOTOs in that example ( try/catch is essentially a 'GOTO catch if something bad happens' ). 是的当然是: static final变量可以在静态块中初始化但是 ....在该示例中你有隐式GOTO( 如果发生了不好的事情, try/catch本质上是'GOTO catch' )。

If an exception is thrown your final variables will not be initialized. 如果抛出异常,则不会初始化final变量。

Note that the use of static constructs goes against Object-Oriented dogma. 请注意,静态构造的使用违背了面向对象的教条。 It may complicate your testing and make debugging more difficult. 它可能使您的测试复杂化并使调试更加困难。

You can do this but you need to exit the static block by throwing an exception - you can rethrow the exception that was caught or a new one. 您可以执行此操作,但需要通过抛出异常来退出静态块 - 您可以重新抛出已捕获的异常或新异常。 Generally this exception must be a RuntimeException . 通常,此异常必须是RuntimeException You really should not catch a generic Exception but more specific exception(s) that might be thrown from within your try block. 你真的不应该捕获一般的Exception但可能会在你的try块中抛出更具体的异常。 Finally, if a static initializer throws an exception then it will render the class unusable during that specific run because the JVM will only attempt to initialize your class once. 最后,如果静态初始化程序抛出异常,那么它将在该特定运行期间使该类不可用,因为JVM将仅尝试初始化您的类一次。 Subsequent attempts to use this class will result in another exception, such as NoClassDefFoundError . 后续尝试使用此类将导致另一个异常,例如NoClassDefFoundError

So, to work, your initializer should read something like this: 所以,要工作,你的初始化程序应该是这样的:

static {
    try {
        ...
    } catch (Exception e) {
        e.PrintStackTrace();
        throw new InitializationFailedException("Could not init class.", e);
    }
}

Assuming that InitializationFailedException is a custom RuntimeException , but you could use an existing one. 假设InitializationFailedException是自定义RuntimeException ,但您可以使用现有的RuntimeException

public class MyClass
{
    private static final SomeClass myVar;

    static
    {
        Object obj = null;  // You could use SomeClass, but I like Object so you can reuse it
        try
        {
            obj = new SomeClass(...);    
        }
        catch(WhateverException err)
        {
            // Possibly nested try-catches here if the first exception is recoverable...
            // Print an error, log the error, do something with the error
            throw new ExceptionInInitializerError(err); 
        }
        finally
        {
            myVar = (SomeClass) obj;
        }
    }
}

Assuming no where upstream is in a position to catch either an ExceptionInInitializationError or a general Exception then the program should not ever try to use myVar . 假设没有上游位置可以捕获ExceptionInInitializationError或一般异常,那么程序不应该尝试使用myVar If however those are caught and the program doesn't end, then you need to code to watch for and handle myVar being null (or be happy with NullPointerExceptions coming out all over). 但是如果它们被捕获并且程序没有结束,那么你需要编写代码来监视并处理myVar为null(或者对NullPointerExceptions全部出来感到满意)。

I'm not sure there is a good way to handle this. 我不确定有一个很好的方法来处理这个问题。

Can you put the declaration in the finally block? 你能把声明放在finally块中吗?

try {
    //load file
} catch(IOException e) {
    // horay
} finally {
    HOST=config.get......
}

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

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