Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the program print the height value 0 instead of the one I set?

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
like image 350
jashgopani Avatar asked Jul 30 '19 05:07

jashgopani


2 Answers

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:

  • Constructor of Base class Base() is called,
  • then "Inside Base Const" is printed,
  • method 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.
like image 142
ישו אוהב אותך Avatar answered Nov 14 '22 03:11

ישו אוהב אותך


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.

like image 37
Mike Nakis Avatar answered Nov 14 '22 03:11

Mike Nakis