thatsyou thatsyou - 4 months ago 12
Java Question

What is the difference between static reference variable and instance reference variable in initiating?

I'm confused about an essential thing in java.

public class InitItself1 {

public InitItself1(){}

private InitItself1 me = new InitItself1();
}


Of course I know that the StackOverFlowError will be occurred when creating an instance of the above class. The above class will be initiated recursively itself because of the initiation of the variable "me".

But,

public class InitItself2 {

public InitItself2(){}

private static InitItself2 me = new InitItself2();
}


Of course the outcome of the above class, "InitItself2" is different to the prior class, "InitItself1". This works just fine, no error occurred. As I know, initiating static variables and executing static blocks are performed when classes in which static variables and blocks are loaded.

What makes me confused is that I think it's the same that the variables, "me" of both classes, "InitItself1" and "InitItself2" are initiated, and also they have references to their classes in which they are, so it looks that "initiating recursively" would happen in initiating both classes.

What is the point that I'm missing?
Good answer please.
Thanks :)

Answer

You are not going to get StackOverFlowError in the second case. As you have said yourself, static variables are initiated when the class is loaded, and because a class is only loaded once, the static InitItself2 me will only be instantiated once. Creating a new object with constructor doesn't require the class to be reloaded.

public final class InitItself {

    static {
        System.out.println("Class is loaded");
    }

    private static InitItself me = new InitItself();

    static {
        System.out.println("me is instantiated");
    }

    public InitItself() {
        System.out.println("Constructor called, me=" + me);
    }

    public static void main(String[] args) {
        System.out.println("START");
        InitItself i = new InitItself();
        System.out.println("FINISH");
    }
}

Gives the following output

Class is loaded
Constructor called, me=null
me is instantiated
START
Constructor called, me=oop.InitItself@6ff3c5b5
FINISH