File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

What will this program print out? Why?

 
Neha Monga
Ranch Hand
Posts: 34
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello All!

Pls explain why the below code will print out 40?

class Base {
int value = 0;
Base() {
addValue();
}
void addValue() {
value +=10;
}
int getValue() {
return value;
}
}

class Derived extends Base {
Derived() {
addValue();
}
void addValue() {
value +=20;
}
}

public class Test {
public static void main(String args[]) {
Base b= new Derived();
System.out.println(b.getValue());
}
}

ANS is 40.
 
anil kumar
Ranch Hand
Posts: 447
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi

The object which has to be executed is resolved at run time.In your case the object is Derived .And you have overridden the addValue method,so while executing the Base constructor ,the object is of derived type,so the method which is overridden will be executed.
So 2 times the same method will be executed.
Execute the below program,i made two changes see line 1 and line 2

class Base {
int value = 10;//line 1
Base() {
addValue();
}
void addValue() {
value +=10;
}
int getValue() {
return value;
}
}

class Derived extends Base {
int a=30;//line 2
Derived() {
addValue();
}
void addValue() {
value +=20;
}
}

public class Test {
public static void main(String args[]) {
Base b= new Derived();
System.out.println(b.getValue());
}
}


Thanks
Anil Kumar
 
Marc Wentink
Ranch Hand
Posts: 142
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think because also in the constructor of the super class the polymorphic version of addValue is called. Hence, two adds 20 make 40.

But man, this really is difficult stuff, I would have said 30 at first sight.
 
krishna bulusu
Ranch Hand
Posts: 185
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This is not at all difficult once you understands the run time polymorphism.
Here one should see the which object not the which reference as object will contain the atual data not the reference!!!
reference simplt points to the object.
Here we are making the object of child not the base!!!
so, the method of the child will be called at the run time.
and remember that the state of the objec tis its instant variables not the method!!!

thanks®ards
krishna
 
Shiva Shankar
Ranch Hand
Posts: 31
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
When excuting
Base b= new Derived();
it will call Derived class constructor,that internally calls Base class constructor,there it will get value=10 because of addValue() call in Base class constructor.after that it comes to Derived class constructor again there is a call to addValue() method again it will call addValue() method of Base class(not Derived addValue() because object is not at all existed for Derived class as we are in Derived class constructor.) the value becomes 20.
when it executes
System.out.println(b.getValue()); in main method it will call addvalue() of Derived class there it becomes 40.

Let me know if you have any questions.
 
ahmed yehia
Ranch Hand
Posts: 424
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Try the code below and you will see that the derived version of
addValue() will get called twise


output:
2
2
40
 
Meena R. Krishnan
Ranch Hand
Posts: 178
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Just to add to all these, polymorphism apply only to the methods.

If you have the same instance variable in both base and derived and accessing this instance variable directly ( through an object instantiation w/o through a method) will get you the reference type's variable.

 
Meena R. Krishnan
Ranch Hand
Posts: 178
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Here is a link you can read about variable shadowing and method overriding with examples.
 
Neha Monga
Ranch Hand
Posts: 34
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks all...

the concept is very much clear now....
 
krishna bulusu
Ranch Hand
Posts: 185
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank god!!!
Atlast you got it
 
Raghavan Muthu
Ranch Hand
Posts: 3381
Mac MySQL Database Tomcat Server
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thats a great flow of answers.

A small correction to what Shiva shankar said.


after that it comes to Derived class constructor again there is a call to addValue() method again it will call addValue() method of Base class(not Derived addValue() because object is not at all existed for Derived class as we are in Derived class constructor.)



Thats not actually right. Soon after you invoke



an object of the Derived class is created. Then to prepare or make the object completely ready, the constructor chaining occurs..

If you can debug the flow using an IDE (say, eclipse) you can see that soon after the constructor of derived class is invoked, the following things happen.

  • The flow goes to the Derived Class Constructor's method definition (not inside the method!!)
  • The object being instantiated now becomes as that of Derived (which was originally showing as this which was of the Test class whose main() method was invoking the Derived Class object.
  • As the derived class object is created, as i said earlier, "to make it completely ready/filled", the constructor chaining occurs. Means the flow goes to the Base Class constructor
  • In the base class's constructor, the method addValue() is invoked. Since because there is an Derived Class Object existing, the method belonging to Derived Class is invoked!!. As "Ahmed Yehia" pointed out, it prints "2" to show that the method pertaining to Derived Class is invoked certainly NOT the base class version
  • Once the constructor execution in base class is done, the flow is returned back to the original place of calling. i.e, the derived class constructor. Again, there is a call to addValue() method, which is as usual with respect to the actual object calling which is nothing but of derived class object. So, the same method in derived class is called once again.



  • Hope this clears.

    Am i wrong somewhere especially about the part of object creation and initialization? Please let me know if in case.
    [ May 22, 2007: Message edited by: Raghavan Muthu ]
     
    Sanjeev Kulkarni
    Greenhorn
    Posts: 26
    • 0
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Just wanted to add a variant to the whole scenario.

    If your Derived doesn't have addValue(), the addValue() of Base will be invoked and you can see that the same gets called twice, before the value(=20) is printed out to the console!

    Moral of the Story:

    All the super classes(chained ones) of the subclass will be initialized before subclass instance is created.
    If Parent class method isn't overridden in the Child class, then that Parent class method is invoked at run-time for the instance of Child class too!
     
    Raghavan Muthu
    Ranch Hand
    Posts: 3381
    Mac MySQL Database Tomcat Server
    • 0
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Hi sanjeev,


    All the super classes(chained ones) of the subclass will be initialized before subclass instance is created.
    If Parent class method isn't overridden in the Child class, then that Parent class method is invoked at run-time for the instance of Child class too!


    That really adds a feather to the crown!!

    Thanks buddy
     
    madhu v pe
    Ranch Hand
    Posts: 100
    • 0
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Hi all,
    well defined

    as sanjeev added one feather for our Overrinding Crown.
    a feather for Overloading Crown.

    If Base class method is Overloaded in the Derived class, then that Base class method is invoked at run-time for the instance of Derived class too.

    another Moral is:
    when base class reference is pointing to Derived class object, if derived class is overloading base class method, always base class method will be called.
    simply overloading method calling depends on the Base class
    overriding method calling depends on the Derived class

    for example:




    Thanks
     
    Raghavan Muthu
    Ranch Hand
    Posts: 3381
    Mac MySQL Database Tomcat Server
    • 0
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    That is really nice to add the point!

    Thanks Madhu
    [ May 24, 2007: Message edited by: Raghavan Muthu ]
     
    Sergio Tridente
    Ranch Hand
    Posts: 329
    Java Linux Oracle
    • 0
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Originally posted by madhu v pe:
    when base class reference is pointing to Derived class object, if derived class is overloading base class method, always base class method will be called.
    simply overloading method calling depends on the Base class
    overriding method calling depends on the Derived class


    madhu,

    Check this out:


    As a matter of fact, when overloading method you have to take into consideration two things: reference type (as oppossed to real class type) and argument(s) type.

    The reference type gives you methods' "visibility" (i.e. which methods are visible). Then from the visible methods, it'll choose the one whose arguments types are 'closest' to the ones used in the call.

    In the examples I gave you: when using a Base class reference, it will see only the Base class' methods and it will choose from them. But, when using a Derived class reference, then methods in both classes are visible (OK, depending on access modifiers) and then it will use those to decide whihc one fits better for the method call.

    Try my little program.
     
    madhu v pe
    Ranch Hand
    Posts: 100
    • 0
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Yes Tridente,
    I tried your example.
    so the statement I have given are not a conclusion.
    still some more missing points are there.
    will dig them also

    my doubt is on ((Derived)b).method(2); Vs ((Derived)b).method2(6);
    d.method(4); Vs d.method2(8);

    Pls can you provide any source for these points, like where can i find this information? or where you found this info.

    Thanks in advance
     
    Raghavan Muthu
    Ranch Hand
    Posts: 3381
    Mac MySQL Database Tomcat Server
    • 0
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Hi Serigo,

    Can you just explain the invocation steps (8 statements) you had given?



    As madhu pointed out, the typecasting steps seems to be a little bit confusing.

    Thanks!
     
    rajesh baba
    Greenhorn
    Posts: 25
    • 0
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    class A
    {
    A()
    {
    System.out.println("inside A");
    }
    }
    class B extends A
    {
    B()
    {
    System.out.println("inside b");
    }
    }
    class c extends B
    {
    c()
    {
    System.out.println("inside c");
    }
    }
    class test
    {
    public static void main(String args[])
    {
    c obj=new c();
    }
    }
    output will be
    inside A
    inside B
    inside c
    ------------------------------------------------------------
    so in you progam also
    addValue() will be called twice at the same time method of subclass is called as it is overridden
    so you will get an out put
    40
     
    Sergio Tridente
    Ranch Hand
    Posts: 329
    Java Linux Oracle
    • 0
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Originally posted by Raghavan Muthu:
    Can you just explain the invocation steps (8 statements) you had given?


    OK. I'll do my best.


    First thing: remember, for overloading you need to take into consideration reference variable type.

    Among the 8 exmples I posted, there are only two basic cases:

    1) Reference type is Base:


    In this case, the compiler sees only two methods (because reference type is Base):


    Now it has to pick up the right method for each call. In this case is easy because there is no averloading at all, so it doesn't matter that the parameter is an int: it'll get promoted to long when necessary (method2).

    2) Reference type is Derived:


    Now the compiler sees 4 methods:


    Note that each method is overloaded now: both have a version that takes an int and another that takes a long.
    So, when picking up the right method the compiler will take the one that fits better: as the parameter is always an int, it'll choose the int version of each method:

    ((Derived)b).method(2); --> Base
    d.method(4); --> Base
    ((Derived)b).method2(6); --> Derived
    d.method2(8); --> Derived


    So, what's the conclusion?

    My idea is that, in general, when you have to deal with a more complicated scenario, where you are given both averloaded and overriden methods, the best approach is to divide the problem in two: what happens at compile time and what happens at runtime.

    At compile time the compiler is only able to deal with reference types, therefore it will react accordingly to the reference type. At this stage you'll know which methods are accesible to each reference type.

    Then the JVM (runtime) will come into play, and it will choose the method it calls depending on the class type.

    Now an example:

    You have two classes: class B extending class A, with the following methods:

    A.method(int)
    A.method(long)
    B.method(int)
    B.method(long)

    and the following call:

    A a = new B();
    byte param = 1;
    a.method(param);

    What will happen?

    - At compile time, the compiler will be able to see only these methods:
    A.method(int)
    A.method(long)

    and it'll choose A.method(int)

    - At runtime, when calling method(int) the JVM will use the one defined in class B, the class type, therefore calling B.method(int)

    I hope I was clear.
    [ May 25, 2007: Message edited by: Sergio Tridente ]
     
    Sergio Tridente
    Ranch Hand
    Posts: 329
    Java Linux Oracle
    • 0
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    For an example of what I wrote before, try executing this piece of code:



    Specially the otput for:

    [ May 25, 2007: Message edited by: Sergio Tridente ]
     
    Raghavan Muthu
    Ranch Hand
    Posts: 3381
    Mac MySQL Database Tomcat Server
    • 0
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Thats really great Sergio.

    Thanks a lot
    [ May 28, 2007: Message edited by: Raghavan Muthu ]
     
    • Post Reply
    • Bookmark Topic Watch Topic
    • New Topic