#152 Constructor should not call any non-final methods

open
nobody
Check (274)
5
2012-10-10
2003-04-02
Simon Kitching
No

The following suggestion for a new check is inspired by
"Effective Java Programming Language Guide" by Joshua
Bloch.

A constructor should never call any method which is
overridable in a subclass because the subclass method
will be called before the subclass constructor.

Example:

public class Super {
public Super() {
m();
}

public void m() {
}
}

public class Sub() {
Date date;

public Sub() {
date = new Date();
}

public void m() {
System.out.println(date);
}
}

When an instance of Sub is created, an attempt is made
to access member date before it is initialised.

Discussion

  • Lars Kühne
    Lars Kühne
    2003-04-05

    Logged In: YES
    user_id=401384

    yes, good suggestion.

    Implementors should be aware of the fact that methods can be
    implicitly final if their declaring class is private or
    final, or if there are only private constructors.

    BTW: This is Item 15, p. 80 in the book.

     
  • Logged In: YES
    user_id=746148

    I agree this is a interesting suggestion but there are two more
    complicated cases for this rule (it would be greate
    if the check will be
    able to catch these problems too):

    --- final_test.java ---
    public
    class final_test {
    public final_test() {
    final_method();
    }

    public final void final_method() {
    non_final_method();
    }

    public void non_final_method() {
    System.err.println("parent's
    method");
    }

    public static void main(String[] args) {
        new
    

    child();
    }
    }

    class child extends final_test {
    Object
    object;

    public child() {
        object = new Object();
    }
    

    public void non_final_method() {

    System.err.println(object.hashCode());
    }
    }
    --- end of
    final_test.java ---
    --- final_test1.java ---
    public class final_test1 {

    public final_test1() {
    external.do_something(this);
    }

    public void method() {
    System.err.println("Parent's method");

    }

    public static void main(String[] args) {
        new final_test1();
    

    new child1();
    }
    }

    class child1 extends final_test1 {

    Object object;

    public child1() {
        object = new Object();
    

    }

    public void method() {
    

    System.err.println(object.hashCode());
    }
    }

    class
    external {
    public static void do_something(final_test1 test) {

    test.method();
    }
    }
    --- end of final_test1.java ---