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

38,279

Solution 1

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').

If an exception is thrown your final variables will not be initialized.

Note that the use of static constructs goes against Object-Oriented dogma. It may complicate your testing and make debugging more difficult.

Solution 2

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 Exception but more specific exception(s) that might be thrown from within your try block. 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.

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.

Solution 3

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. 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).

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

Share:
38,279

Related videos on Youtube

Amit
Author by

Amit

Updated on November 25, 2020

Comments

  • Amit
    Amit over 3 years

    Based on my understanding of the Java language, static variables can be initialized in static 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:

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

  • Amit
    Amit over 14 years
    Can I throw exception from static initialization block. What can I do when a code in static initialization block throw some exception which I don't want to handle.
  • awk
    awk over 14 years
    you can initialize the variables outside of the try catch block, e.g. doing the exception throwing code in try catch and initializing in finally...
  • Kevin Brock
    Kevin Brock over 14 years
    @awk: he would need to use locals to do the assignment if the exception throwing code is the getString(...) method call.
  • awk
    awk over 14 years
    @Kevin of course, the final variables have to be assigned to something, so in the catch block he would probably assign it to null
  • Daniel
    Daniel over 13 years
    It is no problem if there is an exception in the static block you DON'T handle, because this will throw an exception during initialization of the class and init will fail, instead of as seen in the example given, where it could potentially success without initialization of all variables.
  • jtahlborn
    jtahlborn over 13 years
    e.printStackTrace() by itself in a catch block makes me cry.
  • sactiw
    sactiw about 12 years
    @YatendraGoel Just to add to this answer this is also true for instance level (non static) final fields as well
  • sactiw
    sactiw about 12 years
    >>> then you need to code to watch for and handle myVar being null Here the static initializer throws an exception which prevents the class from being loaded at all (and thus the variables cannot be referenced uninitialized) thus no need to worry for NPE (null pointer exception)
  • Piyush-Ask Any Difference
    Piyush-Ask Any Difference over 11 years
    You need to make sure that the final static variables are initialized before you exit the static block. In your case, initialize them in the catch block too or better use finally block depending upon your requirement