125

When are static fields initialized? If I never instantiate a class, but I access a static field, are ALL the static blocks and private static methods used to instantiate private static fields called (in order) at that instant?

What if I call a static method? Does it also run all the static blocks? Before the method?

Top-Master
  • 7,611
  • 5
  • 39
  • 71
Tony R
  • 11,224
  • 23
  • 76
  • 101

3 Answers3

167

A class's static initialization normally happens immediately before the first time one of the following events occur:

  • an instance of the class is created,
  • a static method of the class is invoked,
  • a static field of the class is assigned,
  • a non-constant static field is used, or
  • for a top-level class, an assert statement lexically nested within the class is executed1.

See JLS 12.4.1.

It is also possible to force a class to initialize (if it hasn't already initialized) by using Class.forName(fqn, true, classLoader) or the short form Class.forName(fqn)


When does static class initialization happen?

See above.

When are static fields initialized?

As part of static class initialization; see above.

If I never instantiate a class, but I access a static field, are ALL the static blocks and private static methods used to instantiate private static fields called (in order) at that instant?

Yes. (Modulo that nothing is truly instantaneous.)

What if I call a static method? Does it also run all the static blocks? Before the method?

Yes and yes.


Note that it is possible to construct code where you can observe the default initialized value of a static field.


1 - The final bullet point was present in the JLS for Java 6 through Java 8, but it was apparently a mistake in the specification. It was finally corrected in the Java 9 JLS: see source.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • 13
    There is a common pitfall though. Primitives and `String`s are substituted and not referenced. If you reference a `class Other { public static final int VAL = 10; }` from some class `MyClass { private int = Other.VAL; }`, the class `Other` will not be loaded. Instead, the compiler will simply substitute the final field at compile time. – Rafael Winterhalter Oct 28 '13 at 09:45
  • 7
    @RafaelWinterhalter - yes ... that is the **constant** static field case. – Stephen C Dec 14 '15 at 03:03
  • 2
    @RafaelWinterhalter, this is not true for all 'static final' primitive or `String` variables, only ones initialized by a constant expression. – Lew Bloch May 23 '17 at 00:54
  • 1
    Yes, and the field does not even need to be `static` while this is common case. – Rafael Winterhalter May 23 '17 at 05:40
  • @StephenC is it also true regarding Androi with Java development? – Idan Damri Jan 27 '20 at 14:45
  • 1
    It is the same programming language. Yes. – Stephen C Jan 27 '20 at 14:56
  • 2
    @RafaelWinterhalter but when the field is not `static`, you need a reference to an instance of it (the compiler will embed a `null`-check even when using the constant value afterwards), so reading a non-`static` constant field will not trigger a class initialization, but the initialization has happen already anyway, when the instance was created (if not even earlier) – Holger Apr 08 '22 at 09:19
15

Static fields are initialized during the initialization "phase" of the class loading (loading, linking and initialization) that includes static initializers and initializations of its static fields. The static initializers are executed in a textual order as defined in the class.

Consider the example:

public class Test {

   static String sayHello()  {
      return a;
   }

   static String b = sayHello(); // a static method is called to assign value to b.
                                 // but its a has not been initialized yet.

   static String a = "hello";

   static String c = sayHello(); // assignes "hello" to variable c

    public static void main(String[] arg) throws Throwable {
         System.out.println(Test.b); // prints null
         System.out.println(Test.sayHello()); // prints "hello"
    }
}

The Test.b prints null because when the sayHello was called in static scope, the static variable a was not initialized.

naikus
  • 24,302
  • 4
  • 42
  • 43
  • 6
    Strictly speaking, initialization is not a "phase" of class loading. Indeed, some classes *may* be loaded but never initialized if the application doesn't actually make use of them. – Stephen C Aug 17 '10 at 04:51
  • @Stephen C You are right, I used it for a lack of a better term, maybe i'll quote it. – naikus Aug 17 '10 at 05:09
  • @StephenC does that mean while the Class loading takes place, it assigns memory to static variables (& methods) but those static variables aren't initialized with values provided in code? because here it seemd when b->sayHello()->a, 'a' is in memory but value to it is yet not assigned. – Shabbir Essaji Feb 06 '18 at 07:36
  • Basically, yes. – Stephen C Feb 06 '18 at 08:09
  • @StephenC please, could you give some details? As I know in the linking phase it allocates memory for static variables and assigns them a default value. Then in the initialization phase, it assigns them with original values. In this example, `b` is null, because in the initialization phase static blocks are executed from parent to child and from top to bottom. – Hayk Mkrtchyan Jan 24 '22 at 10:41
  • You have got it correct. I don't know why you want me to explain something you already understand. (But it is not *just* the static blocks. All static initializations are executed in order, from the start of the class. Like the answer says.) – Stephen C Jan 24 '22 at 10:50
1

Yes, all static initializers are run before you access class first time. If it was any other way, I would call it a bug.

Nikita Rybak
  • 67,365
  • 22
  • 157
  • 181