Monday, 11 May 2015

Java: In superclass, constructors must not invoke overridable methods

N.B: The superclass constructor runs before the subclass constructor, so the overriding method in the subclass will get invoked before the subclass constructor has run.
If the overriding method depends on any initialization performed by the subclass constructor, the method will not behave as expected.

Let's do a case-study:

superclass:
-------------
public class Super {
// Broken - constructor invokes an overridable method
public Super() {
overrideMe();
}
public void overrideMe() {
}
}

subclass:
-----------
public final class Sub extends Super {
private final Date date; // Blank final, set by constructor
Sub() {
date = new Date();
}

// Overriding method invoked by superclass constructor
@Override public void overrideMe() {
System.out.println(date);
}

public static void main(String[] args) {
Sub sub = new Sub();
sub.overrideMe();
}
}


output: 
---------
prints out null the first time, because the overrideMe method is invoked by the Super constructor
before the Sub constructor has a chance to initialize the date field.

2 comments:

  1. Will it change the output when its runs for 2nd time ?
    I think It will always call super class version of method .

    ReplyDelete
  2. Let's say:
    Sub sub = new Sub();
    sub.overrideMe();

    sop: null as date is not yet initialized.

    But after sub.overrideMe() is called, sub() constructor is hit and date gets initialized.

    So again if we write:
    sub.overrideMe(), it would return date value as initialized.

    ReplyDelete