2

Code:

class A{

    A()  {
        test();
    }
    void test(){
        System.out.println("from A");
    }
}

class B extends A {

    void test() {

        System.out.println("from B");

    }

}

class C {

    public static void main(String args []){

        A a = new B();

        a.test();
    }
}

Output:

from B 
from B

Why is it getting printed that way ?

Sandeep Chatterjee
  • 3,220
  • 9
  • 31
  • 47
Aamir
  • 2,380
  • 3
  • 24
  • 54

6 Answers6

3

This is extremely bad code. What's happening is that void test() is being overridden in the child class B.

new B(); creates an instance of class B. The fact that you reference cast it to A is not relevant here. But even though the child class has not yet been constructed, the Java runtime calls a method in that child class from the constructor of the parent class A.

Use this (anti)pattern with extreme caution! (Note that in C++ you get undefined behaviour).

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
2

During runtime, the method is invoked from actual instance object. i.e B.

A a = new B();
a.test();

In the above code, You have instantiated Object B, not A. You have just assigned the reference variable of type A. Internally, it is referring only an instance of B. During compilation, it just checks whether the method is actually present in A reference and allow it to compile. During Runtime, the method is actually invoked on the real object i.e. B referred by the reference A

Keerthivasan
  • 12,760
  • 2
  • 32
  • 53
2

This is one of the most important concepts of Object Oriented polymorphism. By extending A with class B you are creating a more specific implementation of it, overriding some of its methods with new ones (such as your test() method) and potentially adding things to it (members and methods).

Whenever you override a class, the methods of the subclass will be invoked, irrespective of which class they are 'acting' to be.

When you cast an object to another class (like in your case B to A) you are just saying I want to see it as a reference of type A. This is useful for methods that accept objects of type A as parameter.

Consider this example:

Employee (super class) which has method float computeSalary()

Technician extends Employee which overrides method float computeSalary()

Manager extends Employee which overrides method float computeSalary()

The SalaryGenerator class has a method generateMonthlyPay(Employee e) that calls the computeSalary() of the Employee superclass, but the specific sub-class method will be invoked, because each have a different way of calculating their monthly salary.

jbx
  • 21,365
  • 18
  • 90
  • 144
2

When you call a polymorphic method at runtime, Java uses a special data structure to decide a method of which class needs to be called. This structure is set up at the time the object is constructed, before any of the user-supplied constructor and initializer code get executed.

When you create A a = new B(), the data structure that says "when test() is called, you need to call A.test() or B.test()" is prepared before the constructor of A is entered. Since this structure is prepared for the B class, it points to B.test(), even though the calling code is inside A's constructor. That is why you see "from B" printed twice.

Note, however, that although technically your code will do what you want, logically it is a very poor decision. The reason why this code is bad has to do with the initialization sequence: imagine a test() method that relies on private fields of B being initialized in the constructor, like this:

class B extends A {
    private final String greeting;
    public B() {
        greeting = "Hello";
    }
    void test() {
        System.out.println(greeting + " from B");
    }
}

One would expect to see "Hello from B" being printed. However, you would see it only in the second call: at the time the first call is made, greeting is still null.

That is why you should avoid calling method overrides from inside a constructor: it breaks method's assumption that the object has been fully initialized, sometimes with rather unfortunate consequences.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
1

Although the reference type is A, it's object type is B which means that it is pointing to the implementation in B. Hence, from B gets printed.

ucsunil
  • 7,378
  • 1
  • 27
  • 32
  • can u plz elaborate a little bit; – Aamir Mar 04 '14 at 16:59
  • In java, the method being executed depends on the object type and not on the reference type. A a = new B(); indicates that your object type is B. So now when you create an object of type B, it's constructor is first called which will chain to the super class constructor (in this case class A) and run the method test() which will print from B as the object type B overrides test() in it. Now you are again calling test which will print from B again - your reference type will always point to an implementation of B. – ucsunil Mar 04 '14 at 17:14
0

When the object a is created using, A a = new B()

the constructor gets invoked from base class to derived class.. here the base class constructor calls test(), but this calls test() in derived class because of the over riding concept.

So you get " from B" initially.

Again a.test() calls the over rided derived class test(). So again from B is printed

user3256147
  • 378
  • 2
  • 9