wood burning stoves 2.0*
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes What will this program print out? Why? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Murach's Java Servlets and JSP this week in the Servlets forum!
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "What will this program print out? Why?" Watch "What will this program print out? Why?" New topic
Author

What will this program print out? Why?

Neha Monga
Ranch Hand

Joined: Mar 13, 2007
Posts: 34
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

Joined: Feb 23, 2007
Posts: 447
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

Joined: May 18, 2007
Posts: 142
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.


SCJP5
krishna bulusu
Ranch Hand

Joined: Aug 28, 2006
Posts: 185
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


Thanks&Regards, Krishna.
SCJP1.4, SCWCD1.4, SCBCD 5.0
Shiva Shankar
Ranch Hand

Joined: Dec 07, 2006
Posts: 31
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

Joined: Apr 22, 2006
Posts: 424
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

Joined: Aug 13, 2006
Posts: 178
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

Joined: Aug 13, 2006
Posts: 178
Here is a link you can read about variable shadowing and method overriding with examples.
Neha Monga
Ranch Hand

Joined: Mar 13, 2007
Posts: 34
Thanks all...

the concept is very much clear now....
krishna bulusu
Ranch Hand

Joined: Aug 28, 2006
Posts: 185
Thank god!!!
Atlast you got it
Raghavan Muthu
Ranch Hand

Joined: Apr 20, 2006
Posts: 3344

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 ]

    Everything has got its own deadline including one's EGO!
    [CodeBarn] [Java Concepts-easily] [Corey's articles] [SCJP-SUN] [Servlet Examples] [Java Beginners FAQ] [Sun-Java Tutorials] [Java Coding Guidelines]
    Sanjeev Kulkarni
    Greenhorn

    Joined: Mar 20, 2006
    Posts: 26
    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

    Joined: Apr 20, 2006
    Posts: 3344

    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

    Joined: Apr 21, 2007
    Posts: 100
    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

    Joined: Apr 20, 2006
    Posts: 3344

    That is really nice to add the point!

    Thanks Madhu
    [ May 24, 2007: Message edited by: Raghavan Muthu ]
    Sergio Tridente
    Ranch Hand

    Joined: Mar 22, 2007
    Posts: 329

    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.


    SCJP 1.4 (88%) - SCJP 5.0 Upgrade (93%) - SCWCD 1.4 (97%) - SCBCD 5.0 (98%)
    madhu v pe
    Ranch Hand

    Joined: Apr 21, 2007
    Posts: 100
    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

    Joined: Apr 20, 2006
    Posts: 3344

    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

    Joined: May 19, 2007
    Posts: 25
    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

    Joined: Mar 22, 2007
    Posts: 329

    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

    Joined: Mar 22, 2007
    Posts: 329

    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

    Joined: Apr 20, 2006
    Posts: 3344

    Thats really great Sergio.

    Thanks a lot
    [ May 28, 2007: Message edited by: Raghavan Muthu ]
     
    Consider Paul's rocket mass heater.
     
    subject: What will this program print out? Why?
     
    Similar Threads
    initialisation & control flow
    how is the flow
    confusion in the output
    question from Sahir's Mock Exam
    polymorphism Problem (tricky)