简体   繁体   中英

Java : in what order are static final fields initialized?

Okay, so say I have a class that looks like this :

public class SignupServlet extends HttpServlet {
    private static final Logger SERVLET_LOGGER=COMPANYLog.open(SignupServlet.class);
    private static final ExceptionMessageHandler handler = new ExceptionMessageHandler();   
    private static final SignupServletObservableAgent signupObservableAgent = 
        new SignupServletObservableAgent(null, SERVLET_LOGGER);
}

Can I count on the class loader to initialize those fields in order, such that I can rely on SERVLET_LOGGER to be instantiated before signupObservableAgent?

Yes, they are initialized in the order in which they appear in the source. You can read all of the gory details in The Java Language Specification, §12.4.2 . See step 9, which reads:

... execute either the class variable initializers and static initializers of the class, or the field initializers of the interface, in textual order, as though they were a single block, except that final class variables and fields of interfaces whose values are compile-time constants are initialized first ...

I think that initialization of static fields could be re-ordered. At least that is how I understand JMM specification

There are a number of cases in which accesses to program variables (object instance fields, class static fields, and array elements) may appear to execute in a different order than was specified by the program.

if sub class and super class is there.

  1. EX: 'A' : super class 'B' : sub class and it extends super class 'A'
  2. when B class loaded then A class also loads
  3. all static variables get memory with default value from 'A' and 'B' class
  4. then static members (static variable,static block) are executed in top to bottom order of 'A' class and then 'B' class in order they declared . finally main method executed from sub class automatically.

Not really answering the question, but asking more here -) . Just came across an interesting example with static field initialization order. Here is the example:

   public class Foo {

    private static final Long result = method1();

    private static String string = "something";

    private static Long method1() {
        if (string == null) {
            throw new IllegalStateException("BOOM");
        }
        return 1L;
    }

    public static void main(String[] args) {
        System.out.println("here");
    }
}

This will produce IllegalStateException. I understand that the sequence here is that first we evaluate "result" field which calls method1() and bypasses "string" value initialization. "string" is meant to be a constant, but I forgot to put a "final" modifier when wrote tests. But should such cases be handled in the runtime? Meaning when we invoke "if (string == null)" should JRE to be smart enough to go and verify that "string" has not been initialized and initialize it?

This is a place where you can use a static block which would guarantee the sequence of execution.

public class SignupServlet extends HttpServlet {
   private static final Logger SERVLET_LOGGER;
   private static final ExceptionMessageHandler handler;
   private static final SignupServletObservableAgent signupObservableAgent;

   static {
      SERVLET_LOGGER = COMPANYLog.open(SignupServlet.class);
      handler = new ExceptionMessageHandler();
      signupObservableAgent = new SignupServletObservableAgent(null, SERVLET_LOGGER);
   } 
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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