Numerator
Numerator

Reputation: 1409

Java- why does it print null?

public class Base {
public Base() {
    x = 0;
    bar();
}

public Base(int x) {
    this.x = x;
    foo();
}

public void foo() {
    System.out.println("Base.foo : " + x);
}

private void bar() {
    System.out.println("Base.bar:" + x.toString());
}

protected Integer x;
}

    public class Derived extends Base {
       public Derived() {
       bar();
       }
       public Derived(int x, int y) {
         super(x);
         this.y = y;
       }
       public void foo() {
         System.out.println("Derived.foo : " + x + ", " + y);
       }
       public void bar() {
         System.out.println("Derived.bar:" + x.toString() + ", " + y.toString());
       }
       private Integer y;


       public static void main(String[] args) {
        Base b = new Derived(10, 20);
      }
}

Why does it print "Derived.foo:" 10, nulll and not 20 instead of the null? y is a private variable of Derived, and it was initialized with 20. it's in its scope.. so why is it null?

Upvotes: 5

Views: 1590

Answers (8)

Matthew Blackford
Matthew Blackford

Reputation: 3051

If you follow the calls from the constructor it makes it clearer:

  1. Calls the Derived(int x, int y) constructor
  2. Calls the super constructor Base(int x)
  3. Sets the x variable
  4. Calls the overridden foo() method
  5. Performs the println()
  6. Then sets the y variable

As you can see, the y variable is getting set after you try to print out the value. That is why you are seeing the uninitialized value of null.

Calling overridable methods from a constructor is a common mistake, as it can allow uninitialized variables to escape before the object is fully constructed.

Upvotes: 2

mcfinnigan
mcfinnigan

Reputation: 11638

because y has not been initialised when foo() is called in the Base class constructor.

the chain goes main -> Derived(x,y) -> Base(x) -> initialise x, foo(). However, because you're starting the call inside Derived, which overrides foo(), derived's foo() is actually executed by the interpreter.

Upvotes: 1

Roel Van Nyen
Roel Van Nyen

Reputation: 1325

All the answers are indeed correct but next time you can maybe put a breakpoint in the function where you are printing something. Then you can simply examine the call stack and folow the code by reading the parts that are being called.

This way you could have traced that y would not be initialized.

Good luck! Roel

Upvotes: 1

JB Nizet
JB Nizet

Reputation: 691635

Because the super constructor is first called (super(x)). This super constructor calls the method foo. Then the Derived constructor initializes y to 20 (this.y = y). So when foo is called, y is not initialized yet.

It's a bad practice to call overridable methods in constructors, because, as you just noticed, it can call overridden methods on partially constructed objects.

Upvotes: 7

Fabian Barney
Fabian Barney

Reputation: 14549

It is printed by Derived.foo() triggered by Super-Constructor call before it is initialized with 20 afterwards. So while printing it is still null.

Upvotes: 1

Adam Batkin
Adam Batkin

Reputation: 52974

It does that because the superclass (Base) constructor calls Derived.foo() before the y member variable has been set.

So here is the basic order of operations:

main(...)
Derived(10,20) (start constructor)
Base(10) (start constructor)
this.x = x
foo() (calls Derived.foo() which prints the message you see)

Then after that

this.y = y

Upvotes: 2

J Lundberg
J Lundberg

Reputation: 2363

When you get into the constructor of the super class y is not yet instantiated yet. So the call to foo() will have a null y.

Upvotes: 1

Mat
Mat

Reputation: 206679

The println comes from method foo which is called from Base's constructor, which is called from Derived's constructor (via super) before you initialize y. So the null value is expected.

Upvotes: 2

Related Questions