Lecture Notes for Concurrent Programming

8 July 2003 - Immutable Class Instances


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.