Virtual method calls in constructors are a problem because they're virtual: that is, go to the child class instance to execute, and the child class instance may have unitialized fields.
For example, consider the code
$ cat t.java class blob { void msg() { System.out.println("in blob::msg()"); } blob() { msg(); } } class CountingBlob extends blob { private int msgsPrinted; CountingBlob() { msgsPrinted = 10; } void msg() { System.out.println("in CountingBlob::msg(), msgs printed = " + msgsPrinted + "."); } } class t { public static void main(String[] args) { new blob(); new CountingBlob(); } } $
The parent class blob makes a call to the virtual function msg()
. When
constructing a CountingBlob, blob()
is (implicitly) called first in
CountingBlob()
before anything else. blob()
then calls msg()
, which,
because it's virtual, goes to CountingBlob::msg()
and starts executing. And
CountingBlob::msg()
accesses the msgsPrinted field, which has not yet been
explicitly executed.
$ javac t.java $ java t in blob::msg() in CountingBlob::msg(), msgs printed = 0. $
Apart from being undefined behavior in Java, this is dangerous for immutable classes, which are written under the assumption that internal state doesn't change. However, an errant virtual function call can see changing state, which could lead to hellishly subtle errors.
This page last modified on 7 July 2003.