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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2339932/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 06:18:52  来源:igfitidea点击:

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

javastaticfinal

提问by Yatendra Goel

Based on my understanding of the Java language, static variables can be initialized in static initialization block.

根据我对Java语言的理解,静态变量可以用static initialization block.

However, when I try to implement this in practice (staticvariables that are finaltoo), I get the error shown in the screenshot below:

但是,当我尝试在实践中实现这一点时(static变量也是final如此),我收到如下屏幕截图所示的错误:

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

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

采纳答案by SyntaxT3rr0r

Yes of course: static finalvariables can be initialized in a static block but.... you have implicit GOTOs in that example (try/catchis essentially a 'GOTO catch if something bad happens').

当然是的:static final变量可以在静态块中初始化,但是......在那个例子中你有隐含的 GOTOs(try/catch本质上是一个'如果发生不好的事情'GOTO catch')。

If an exception is thrown your finalvariables 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.

请注意,静态构造的使用违背了面向对象的教条。它可能会使您的测试复杂化并使调试更加困难。

回答by Kevin Brock

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. You really should not catch a generic Exceptionbut more specific exception(s) that might be thrown from within your tryblock. 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. Subsequent attempts to use this class will result in another exception, such as NoClassDefFoundError.

您可以这样做,但您需要通过抛出异常退出静态块 - 您可以重新抛出捕获的异常或新异常。通常,此异常必须是RuntimeException. 您真的不应该捕获Exception可能从您的try块中抛出的通用但更具体的异常。最后,如果静态初始化程序抛出异常,那么它将在该特定运行期间呈现该类不可用,因为 JVM 只会尝试初始化您的类一次。后续尝试使用此类将导致另一个异常,例如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 InitializationFailedExceptionis a custom RuntimeException, but you could use an existing one.

假设这InitializationFailedException是一个 custom RuntimeException,但您可以使用现有的。

回答by Stephen

Can you put the declaration in the finally block?

你能把声明放在 finally 块中吗?

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

回答by Matt Vang

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 ExceptionInInitializationErroror a general Exceptionthen the program should not ever try to use myVar. If however those are caught and the program doesn't end, then you need to code to watch for and handle myVarbeing null (or be happy with NullPointerExceptionscoming out all over).

假设上游无法捕获ExceptionInInitializationError或一般异常,那么程序不应尝试使用myVar。然而,如果这些被捕获并且程序没有结束,那么您需要编写代码来观察和处理myVar是否为空(或者对NullPointerExceptions全部出来感到满意)。

I'm not sure there is a good way to handle this.

我不确定是否有处理这个问题的好方法。