-2

Why the output is:

> B.foo(): bar = null 
> B.foo(): bar = B.bar 
>a.bar = A.bar 
>B.foo(): bar =B.bar

BUT not:

> B.foo(): bar = null 
> A.foo(): bar = A.bar 
>a.bar = A.bar 
>B.foo(): bar =B.bar

1) B extends A so doesn't it suppose call to A's class? 2) Why by a.bar class A is called and not B ? 3)May you explain the output? code:

public class A {
    String bar= "A.bar";
    A() { foo(); }
    public void foo() {
        System.out.println("A.foo(): bar = "+ bar);
    }
}
public class B extends A {
    String bar= "B.bar";
    B() { foo(); }
    public void foo() {
        System.out.println("B.foo(): bar = "+ bar);
    }
}
public class C {
    public static void main(String[] args) {
        A a= newB();
        System.out.println("a.bar = "+ a.bar);
        a.foo();
    }
}
Sufian
  • 6,405
  • 16
  • 66
  • 120
user
  • 47
  • 5
  • Please fix your code. It won't compile as is. – Carcigenicate Aug 15 '15 at 02:58
  • why by line:"A a=new B();" the output has two lines? – user Aug 15 '15 at 03:01
  • Methods can be overriden, fields cannot be. [This question might help explain](http://stackoverflow.com/questions/9414990/if-you-override-a-field-in-a-subclass-of-a-class-the-subclass-has-two-fields-wi) why the two fields with the same name aren't treated the same as two methods with the same signature. – Obicere Aug 15 '15 at 03:14

1 Answers1

2

When instantiating a class that has inheritance, the parent's constructor is invoked first.

So in this case, the constructor for A is invoked first. The constructor for B is invoked second.

B.foo(): bar = null  // output from B.foo() invoked from A's constructor
B.foo(): bar = B.bar // output from B.foo() invoked from B's constructor

In both cases, the constructors invoke foo(). Regardless of the fact that foo() is defined in both classes, because foo()'s invocation is polymorphic, and the instance being created is of type B, in both constructor invocations, it's B's foo() method that is called. That's why both output lines start with B.foo(): bar = ....

And finally, the reason why the first line prints = null instead of B.bar is because it is trying to print the value of the bar variable inside the B class before the B class has even started initializing its fields, so the value is still null. B's bar variable only gets initialized after A's constructor has finished its work.

This is why you never want to invoke overrideable methods inside a class constructor. It leads to unexpected behavior like this where you can inadvertently read uninitialized fields. This thread explains this in more detail.

Community
  • 1
  • 1
sstan
  • 35,425
  • 6
  • 48
  • 66