Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Static initializer not invoked for a derived class

Tags:

java

The following Java code does not invoke the static initializer of class B. Why?

Code:

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

    public static void f() 
    {
        System.out.println("f() called");
    }
}

class B extends A 
{
    static 
    {
        System.out.println("B static init");
    }
}

public class App
{
    public static void main( String[] args)
    {
        B.f(); //invokestatic  #16                 // Method com/db/test/B.f:()V
    }
}

Program output:

A static init
f() called

Tested on JDK 1.8.0_25

like image 325
Sergey Alaev Avatar asked Jan 13 '15 13:01

Sergey Alaev


People also ask

What is non static initializer in Java?

Instance variables are initialized using initialization blocks. These blocks are executed when the class object is created and before the invocation of the class constructor. Also, it is not necessary to have initialization blocks in the class.

What is static initializer?

The static initializer is actually invoked later, when the class is initialized, after it has been loaded and linked. That happens when you instantiate an object of a class or access a static variable or method on the class.

Can static block override in Java?

No, we cannot override static methods because method overriding is based on dynamic binding at runtime and the static methods are bonded using static binding at compile time. So, we cannot override static methods.

Is static block inherited?

Static initialzier blocks are not inherited . Static blocks are executed when class is loaded since your base class extends a super class , even the super class definition will be loaded by JVM when referring to your class. Lastly,the instance block can also never be inherited.


2 Answers

There is no such thing as "static constructor". It's a static initialization block, and it is only executed when the class is initialized. Since you are calling a static method of class A (even though you are referring to it via class B), there is no need to initialize class B. Calling B.f(); is the same as calling A.f();.

The static initialization block of class B will be executed if you create an instance of class B or access a static member/method of class B.

Here are the only conditions that trigger class initialization (JLS 12.4.1):

A class or interface type T will be initialized immediately before the first occurrence of any one of the following:

 T is a class and an instance of T is created.

 T is a class and a static method declared by T is invoked.

 A static field declared by T is assigned.

 A static field declared by T is used and the field is not a constant variable (§4.12.4).

 T is a top level class (§7.6), and an assert statement (§14.10) lexically nested within T (§8.1.3) is executed.
like image 114
Eran Avatar answered Sep 29 '22 22:09

Eran


Since only class A defines the method f(), class B is loaded but not initialized.

You could use java -verbose:class MyClassName to check this.

On a jdk6 / jdk 8 machine, this will be printed.

[Loaded App from file:/C:/XXXX/]
[Loaded A from file:/C:/XXXXXX]
[Loaded B from file://C:/XXXXXXX]
A static init
f() called

Class B will be initialized lazily but loaded greedily (since it is being referred).

Change your code to A.f(). Then you will see that B is not loaded.

[Loaded App from file:/C:/XXXX/]
[Loaded A from file:/C:/XXXXX]
A static init
f() called

Note : Class loading and initialization are 2 different things. Check documentation for Class.forName() for details.

like image 36
TheLostMind Avatar answered Sep 29 '22 21:09

TheLostMind