Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Static initializer runs after the constructor, why?

Tags:

I have 2 classes:

Class A:

public class A {     static B b = new B();       static {          System.out.println("A static block");      }       public A() {          System.out.println("A constructor");      } } 

Class B:

public class B {      static {          System.out.println("B static block");          new A();      }       public B() {          System.out.println("B constructor");      } } 

I create a Main class which just creates new A:

public class Main {     public static void main(String[] args) {         new A();     } } 

The output I get is:

B static block A constructor B constructor A static block A constructor 

As you can see, the constructor of A is invoked before its static initializer.

I understand it got something to do with the cyclic dependency I created but I was under the impression the static initializer should always run before the constructor.

What is the reason for this to happen (technically in the java implementation) ?

Is it recommended to avoid static initializers all together ?

like image 450
Aviram Segal Avatar asked Dec 19 '12 08:12

Aviram Segal


People also ask

Which will execute first static block or constructor?

Order of execution When you have all the three in one class, the static blocks are executed first, followed by constructors and then the instance methods.

Why static block executes before main method?

The static blocks always execute first before the main() method in Java because the compiler stores them in memory at the time of class loading and before the object creation. Here, the compiler executes all the static blocks first, and after finishing the static block execution, it invokes the main() method.

Are static variables initialized before constructor?

All static members are always initialized before any class constructor is being called.

When should a static initializer be used?

A static constructor is used to initialize any static data, or to perform a particular action that needs to be performed only once. It is called automatically before the first instance is created or any static members are referenced.


1 Answers

static B b = new B(); 

is before

static {      System.out.println("A static block"); } 

So you require that the B instance be initialized before you print "A static block".

And initializing the B class means you need to create a A instance. So there's no way for "A static block" to be printed before the A instance is constructed.

Yes, the static initialization of A is launched before the constructor is launched but, apart deadlocking, there would be no other solution to the sequence you require.

Note the warning in the specification :

Because the Java programming language is multithreaded, initialization of a class or interface requires careful synchronization, since some other thread may be trying to initialize the same class or interface at the same time. There is also the possibility that initialization of a class or interface may be requested recursively as part of the initialization of that class or interface; for example, a variable initializer in class A might invoke a method of an unrelated class B, which might in turn invoke a method of class A. The implementation of the Java virtual machine is responsible for taking care of synchronization and recursive initialization by using the following procedure [the doc goes on with the complete procedure]

A best practice, in Java as in other languages, is basically to avoid cyclic dependencies as their resolution may be very hard to predict.

like image 61
Denys Séguret Avatar answered Sep 28 '22 02:09

Denys Séguret