0

I was testing java's "statics" a bit and found some things I don't get. Look at these codes:

public class X {
    public static int staticInit = 0;
    public static int staticInitRe = 0;
    public static int classicInitRe = 0;
}

public class Y extends X {
    public static int staticInitRe;
    public static int classicInitRe = 1;
    static {
        staticInitRe = 1;
        staticInit = 1;
    }
}

(where "Re" stands for "redeclared")

I made two Main classes for printing and loading

1.

public class Main {
    public static void main(String[] args) {
        System.out.println("staticInit X: "+X.staticInit);
        System.out.println("staticInitRe X: "+X.staticInitRe);
        System.out.println("classicInitRe X: "+X.classicInitRe);
        System.out.println("");

        System.out.println("staticInit Y: "+Y.staticInit);
        System.out.println("staticInitRe Y: "+Y.staticInitRe);
        System.out.println("classicInitRe Y: "+Y.classicInitRe);
        System.out.println("");

        System.out.println("staticInit X: "+X.staticInit);
        System.out.println("staticInitRe X: "+X.staticInitRe);
        System.out.println("classicInitRe X: "+X.classicInitRe);
        System.out.println("");

        System.out.println("staticInit Y: "+Y.staticInit);
        System.out.println("staticInitRe Y: "+Y.staticInitRe);
        System.out.println("classicInitRe Y: "+Y.classicInitRe);
        System.out.println("");

    }
}

output:

staticInit X: 0
staticInitRe X: 0
classicInitRe X: 0

staticInit Y: 0
staticInitRe Y: 1
classicInitRe Y: 1

staticInit X: 1
staticInitRe X: 0
classicInitRe X: 0

staticInit Y: 1
staticInitRe Y: 1
classicInitRe Y: 1

2.

public class Main {
    public static void main(String[] args) {
        System.out.println("staticInit X: "+X.staticInit);
        System.out.println("");

        System.out.println("staticInit Y: "+Y.staticInit);
        System.out.println("");

        System.out.println("staticInit X: "+X.staticInit);
        System.out.println("");

        System.out.println("staticInit Y: "+Y.staticInit);
        System.out.println("");

    }
}

output:

staticInit X: 0

staticInit Y: 0

staticInit X: 0

staticInit Y: 0

I don't understand what happens with the staticInit variable. In the output of the first snippet, I think it should be respectively 0, 1, 0, 1 or 0, 1, 1, 1, not 0, 0, 1, 1.

I also don't get why in the second snippet it changes to 0, 0, 0, 0 after removing prints of the other variables.

0

1 Answer 1

3

staticInit is a static variable of class X. Therefore, when you access it, only class X is initialized. This is true even when you access it via Y.staticInit. Y.staticInit and X.staticInit are the same variable.

Only when you access the first static variables of Y (Y.staticInitRe in your first snippet), class Y is initialized, which also changes the value of X.staticInit to 1.

On the other hand, X.staticInitRe and Y.staticInitRe are different variables and X.classicInitRe and Y.classicInitRe are different variables.

The first snippet :

    System.out.println("staticInit X: "+X.staticInit); // X is initialized. All all of its 
                                                       // variables are initialized to 0
    System.out.println("staticInitRe X: "+X.staticInitRe);
    System.out.println("classicInitRe X: "+X.classicInitRe);
    System.out.println("");

    System.out.println("staticInit Y: "+Y.staticInit); // Y is not initialized yet
    System.out.println("staticInitRe Y: "+Y.staticInitRe); // Y is initialized: 
                                                           // Y.staticInitRe, 
                                                           // Y.classicInitRe and 
                                                           // X.staticInit are assigned 1
                                                           // before this String is output
    System.out.println("classicInitRe Y: "+Y.classicInitRe);
    System.out.println("");

    System.out.println("staticInit X: "+X.staticInit); // was changed to 1 by Y's
                                                       // static initializer
    System.out.println("staticInitRe X: "+X.staticInitRe); // remains 0
    System.out.println("classicInitRe X: "+X.classicInitRe); // remains 0
    System.out.println("");

    System.out.println("staticInit Y: "+Y.staticInit);
    System.out.println("staticInitRe Y: "+Y.staticInitRe);
    System.out.println("classicInitRe Y: "+Y.classicInitRe);
    System.out.println("");

The second snippet doesn't access any variables or methods of class Y, so class Y is not initialized, and X.staticInit remains 0.

JLS 12.4.1. specifies when a class is initialized:

12.4.1. When Initialization Occurs

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.

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

Since Y.staticInit is not declared in Y, using that field doesn't initialize class Y.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.