0

I have add my question in the comment of the code.

class Parent{
    int num =9; //I think num in Parent class is overrided by the num in Child class. why is the num in the first line of output is still 9?
    { //code block
        System.out.println("Parent constructor code..."+num);
    }

    Parent(){
        System.out.println("Parent constructor run"); 
        show(); //why does this method here invoke the show() method in Child class?
    }

    void show() {
        System.out.println("Parent show..."+num);
    }
}

class Child extends Parent{
    int num = 8; 
    {
        System.out.println("Child constructor code..."+num);
        num = 10;
    }

    Child(){ 
        System.out.println("Child constructor run"); 
        show(); 
    }

    void show() {
        System.out.println("Child show..."+num);
    }
}

public class Test {

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

}

the output is:

Parent constructor code...9
Parent constructor run
Child show...0
Child constructor code...8
Child constructor run
Child show...10

thank you guys! I have figured out that it's a variable shadowing and hiding problem.

  • It invokes the overridden Child class version, because you are actually instantiating Child, not Parent – Stultuske Jul 09 '19 at 13:12
  • At least related: https://stackoverflow.com/questions/3879338/whats-wrong-with-this-example-of-java-property-inheritance – T.J. Crowder Jul 09 '19 at 13:13
  • 1
    "I think num in Parent class is overrided by the num in Child class." - your thinking is wrong, fields can't be overridden, only method can. Defining a field with the same name in a subclass merely shadows the field from the superclass. – Erwin Bolwidt Jul 09 '19 at 13:16
  • Please remember to upvote helpful answers, and accept an answer if it solves your question. Welcome to StackOverflow! – Nick Reed Jul 09 '19 at 14:38

3 Answers3

2

The order of object construction is:

  1. variable declaration and initialization
  2. instance constructor block
  3. constructor

If a class has a parent class, the same order is done for the parent before it is for actual class.

parent first

int num = 9

is evaluated first, num is set to 9 (parent's 1.)

Parent constructor code...9

Instance initializer blocks are executed before a constructor (parent's 2.)

Parent constructor run

The constructor is called (parent's 3.)

Child show...0

The constructor of Parent calls show(). show() is overridden, therefore Child's is called.

Child's 1. and 2. have not been called yet, therefore the overriding num in Child is still 0. *1

then the child

int num = 8

Child's 1. is evaluated

Child constructor code...8

Child's 2. num is set to 10 after this.

Child constructor run

Child's 3.

Child show...10

Child's constructor calling show().

*1:

This is why calling non-final methods in a constructor is very dangerous. Methods tend to rely on a member variable being initialized; they are not at this point.

Were this a non-primitive variable, you might very well run into a NullPointerException if your method tries to access it.

daniu
  • 14,137
  • 4
  • 32
  • 53
1

When java creates a child class, it has to call super() to initialize the parent class - this is so it can instantiate private fields in the super class, or other activities. (This does not create an object of the parent class.) That's why you see Parent constructor code...9 - it's calling the parent code, and printing the parent's num.

Because you create a child class, the child's show() is called in the parent constructor. This is why it's dangerous to call non-final methods in a constructor - if a child overrides them, the child's methods will be called instead.

The child's num is 0 because Java initializes member variables to default values, and your code hasn't yet had a chance to set it to 10.

As for your child code, the num is not being overridden, it is being hidden - only methods can be overridden. That's why your child's show() displays it as 10, once it's properly initialized. If you want to access the parent's variable, you can do this with super.num, but this is often regarded as bad practice, since it can cause confusion.

Nick Reed
  • 4,989
  • 4
  • 17
  • 37
  • 1
    "I'm not sure why it calls the child's show(), nor am I sure why the child's num is 0 - num is uninitialized at that point." > There is no such thing as "uninitialized" for class fields - they are all set to 0 before the constructor is run. – Dorian Gray Jul 09 '19 at 13:36
  • Sure enough, [this answer](https://stackoverflow.com/a/1560704/7431860) explained it to me well. I'll edit my answer accordingly. Learning something new every day - thank you! – Nick Reed Jul 09 '19 at 13:39
  • Also: "I'm not sure why it calls the child's show()," Because you have an instance of child, and so the child's method will be called. – Dorian Gray Jul 09 '19 at 13:52
  • Does that mean that even though the parent constructor is called, the child's method overrides the `show()` call in the super constructor? – Nick Reed Jul 09 '19 at 13:55
  • Yes. Thats why it is very dangerous to call non-final methods within a constructor. – Dorian Gray Jul 09 '19 at 13:59
  • Edited to reflect that, I think I learned more from answering this question than I would've if I had asked it. – Nick Reed Jul 09 '19 at 14:04
0

I think it is because automatically your constructor call super class constructor. ( for our first question. ) nevertheless, you override show so when it meets this method, it call the child method

HelsiWork
  • 11
  • 1