I am confused about how are the methods and constructors called at runtime, since the derived constructor is printed 3 times and the height is printed 0
I have tried printing some messages inside methods and constructors as to know what exactly is happening
public class Derived extends Base{
public static void main(String args[]){
System.out.println("Hello World");
Derived d = new Derived();
}
protected Derived(){
System.out.println("Inside Derived Const");
showAll();
}
protected void showAll(){
System.out.println("Inside Derived showAll");
System.out.println(getClass().getName()+" : "+height);
}
double height = 106.0;
}
class Base{
protected Base(){
System.out.println("Inside Base Const");
showAll();
}
protected void showAll(){
System.out.println("Inside Base showAll");
System.out.println(getClass().getName()+" : "+height);
}
double height = 196.0;
}
I expected the output to be
Hello world
Derived : 106
Base : 196
instead I am getting
Hello World
Inside Base Const
Inside Derived showAll
Derived : 0.0
Inside Derived Const
Inside Derived showAll
Derived : 106.0
It's because you derived the Derived
class from Base
class and shadowing the variable and also overriding the methods.
You're calling the constructor of the Base class whenever you're instantiating the Derived class with:
Derived d = new Derived();
Here what happens when you're calling the above code:
Base()
is called,"Inside Base Const"
is printed,showAll()
is not called because it's being override. Method showAll()
inside the Derived
class is called instead,"Inside Base showAll"
is printed,"Derived : 106.0"
is printed because double height = 196.0;
inside Base class is being shadowed by double height = 106.0;
inside the Derived
class.You have stumbled upon a major deficiency in the workings of java (and other object-oriented languages.) This deficiency is allowed by the compiler, but any decent IDE will detect it and show you a warning, so the fact that you are posting this question tells me that you are compiling without some very important warnings enabled. Go enable as many warnings as you can on your IDE, and your IDE will point the problem out to you. But I will now explain it anyway.
In the constructor of your base class, you are invoking showAll()
. This is a non-final method, so any derived class may override it.
It is a grave mistake to invoke an overridable method from within a constructor.
You see, at the moment that the base class constructor is being invoked, the derived class constructor has not been invoked yet, and the object has not been fully initialized. So, what is simply happening is that at the moment that your base class constructor is running, your statement double height = 106.0;
of your derived class has not been executed yet. That's why the height
member of your derived class appears to contain zero. Zero is simply the default, and 106.0
has not been stored in it yet.
If you enable the right warnings in your IDE, then your IDE will warn you about any invocations of non-final methods from within a constructor. (In my opinion, this should not be a warning, it should be an error.)
So, let me briefly address each of your expectations vs. results:
You expected the following:
Hello world
Derived : 106
Base : 196
That's wrong. If you had no other mistakes, you should have expected the following:
Hello world
Base : 196
Derived : 106
That's because your Derived
constructor starts with an implicit (hidden) call to the Base
constructor, so the base constructor will always be invoked first. This is evident by your System.out.println("Inside X Const")
statements.
But instead you got the following:
Hello World
Derived : 0.0
Derived : 106.0
Both lines appear to come from the 'Derived' class, because getClass()
will return the class of the current object, and you have only created one object, which is an instance of Derived
. So, getClass()
will return Derived
when invoked from within the Derived
class, and it will also return Derived
when invoked from within the Base
class.
And then the 0.0
as I have already explained comes from the uninitialized member variable of the Derived
instance, since you are invoking the showAll()
overridable from within the constructor of the base class, so the derived class has not had a chance to initialize itself at the moment that the method is invoked.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With