user121449
user121449

Reputation: 15

Inheritance, NullPointerException concept of super()

Base Class:

public class Base {
    private String baseMessage = "Hello!";

    public Base() {
        printMessage();
    }

    public void printMessage() {
        System.out.println(baseMessage.toString());
    }
}

Derived Class:

public class Derived extends Base {
    private String derivedMessage = "World!";

    public Derived () {
        super();

    }

    @Override
    public void printMessage() {
        super.printMessage();
        System.out.println(derivedMessage.toString());
    }


    public static void main(String[] args) {
//      new Base();
        new Derived();
    }
}

When I run

new Base();

I get the expected output:

Hello!

When I Run

new Derived();

I get

Hello!
Hello!

then NullPointerException. This seems a bit weird to me. I don't know why it's printing it out then throwing a nullpointerexception, rather straight up throwing it. Maybe it's Eclipse, I don't know.

What's the underlying concept here?

Upvotes: 0

Views: 736

Answers (1)

Sotirios Delimanolis
Sotirios Delimanolis

Reputation: 280136

Before you read this, read

The body of a child class constructor is compiled to something like this

public Derived () {
    super();
    initializeInstanceFields(); 
    // all instance fields are initialized either to their default value
    // or with their initialization expression
}

In other words, by the time the Derived#printMessage() is called because of polymorphism from the super constructor, the Derived.derivedMessage is still null.


Here's the step by step:

new Derived();

invokes the Derived constructor

public Derived () {
    super();
}

which invokes the super constructor

public Base() {
    printMessage();
}

Here, before the printMessage(), this class' instance fields are initialized, so baseMessage gets the value of "Hello!". When printMessage() gets invoked, because this is a Derived object and Derived overrides the methods, its implementation is invoked.

@Override
public void printMessage() {
    super.printMessage();
    System.out.println(derivedMessage.toString());
}

This calls the super implementation

public void printMessage() {
    System.out.println(baseMessage.toString());
}

which prints

Hellow!

The method returns back to Derived#printMessage and attempts to invoke toString() on derivedMessaged, but, as I've explained earlier, the derivedMessage hasn't been initialized yet, so it is null. Dereferencing null causes NullPointerException.

And this is why you don't invoke overridable methods from constructors.

Upvotes: 5

Related Questions