1

I wrote down this mini-program:

A class:

public class A
{

    public A()
    {
        System.out.println(getS());
    }

    public String getS() { return s;}


}

B class:

public class B extends A
{
    private String s = "hello2";

    public String getS() { return s;}

}

main:

public static void main(String[] args)
{
    B b = new B();
}

and it printed:

null

Why is that?
I know that the String that printed is B's string, but why it didn't initialized before?

According to this answer - the variable initialized before the constructor..

EDIT - I edited the code so the unrelated code won't confuse

Community
  • 1
  • 1
Dvir Naim
  • 335
  • 1
  • 3
  • 12
  • 1
    Search for a guide on OO and default constructor. This would be quite obvious then. – AxelH Feb 15 '17 at 14:07
  • 4
    Possible duplicate of [How does the constructor work while initializing an object?](http://stackoverflow.com/questions/23263369/how-does-the-constructor-work-while-initializing-an-object) – Pavel Uvarov Feb 15 '17 at 14:21
  • @dasblinkenlight Thanks! Fixed it.. – Dvir Naim Feb 15 '17 at 16:08

3 Answers3

5

Here is what's going on: when you construct B, the first thing its constructor needs to do is constructing A. This is done before B's own field s is initialized.

A constructs its own s, and then calls getS. However, it does not get its own getS, because B provides an override for it. Recall that B.s has not been initialized yet. That is why you see null printed.

Follow-up reading: What's wrong with overridable method calls in constructors?

Community
  • 1
  • 1
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • http://stackoverflow.com/questions/26552799/which-run-first-default-values-for-instance-variables-or-super-constructors#answer-26553138 - It says here that the varibles initialize before the constractor.. – Dvir Naim Feb 15 '17 at 14:12
  • 1
    @DvirNaim It talks about initializing variables to their default values, not setting them to what their initializers specify. I.e. it says that both `s` will be set to `null` prior to calling constructors. – Sergey Kalinichenko Feb 15 '17 at 14:14
  • oh.. I misunderstood it.. What the logical behind this? Why not initialize first? – Dvir Naim Feb 15 '17 at 14:15
  • @DvirNaim Initializing to non-default values may require running the code (e.g. `String s = myMethodThatMakesAString();`). This shouldn't be done before the class has completed initialization. – Sergey Kalinichenko Feb 15 '17 at 14:22
  • It the same for int variables? – Dvir Naim Feb 15 '17 at 14:39
  • @DvirNaim Yes, except, of course, `int`s are initialized to zero by default. – Sergey Kalinichenko Feb 15 '17 at 14:47
3

What is happening:

You create a B instance, this will call the super() so the constructor of A.

Here it will do the print using the getter getS(). This will use the getter of B since this is the type of this but in this getter, the String is not yet instanciate since it is still doing the super class construction, so it return null.

Note that the String s in A is hidden by the one in B

The order during an instance is :

  • the static (from the super then the class)
  • the super class declaration (statement then constructor)
  • the block statement
  • the constructor

As Seen with :

public class A{
    static{System.out.println("sA");}
    {System.out.println("A1");}

    public Main() {
        System.out.println("new A");
    }

    {System.out.println("A2");}


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

class B extends Main {
    static{System.out.println("sB");}
    { System.out.println("B1"); }

    public B() {
        System.out.println("new B");
    }

    { System.out.println("B2"); }
}

Output :

sA
sB
A1
A2
new A
B1
B2
new B
AxelH
  • 14,325
  • 2
  • 25
  • 55
  • Fix me if I wrong - you saying that the construction is the last thing happened. I know that B's constructor call A's constructor. So the initialize is before B's constructor which is before A's constructor. Am I wrong? – Dvir Naim Feb 15 '17 at 14:37
  • @DvirNaim First, the super class is generated (using the `super` if there is none), then the initialisation of the instance variable and block of statement, then the constructor is executed. This is why the `super` is the first statement that should be present in a constructor (and is added if there is none). Read the example and the output, you will see every step here – AxelH Feb 15 '17 at 14:54
1

it prints null because you have polymorphism in java. You Overrided method getS(). So when you call it from A, you try to call getS() from class B. But you didn't create instance of class B yet, because you need to finish class A first. So String in class B haven't been initialized yet, because of it you get null.