Reputation: 15
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
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