Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Don’t call subclass methods from a superclass constructor

Tags:

java

Consider the following code

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package example0;

/**
 *
 * @author yccheok
 */
public class Main {

    static class A {
        private final String var;

        public A() {
            var = getVar();
            // Null Pointer Exception.
            System.out.println("var string length is " + var.length());
        }

        public String getVar() {
            return "String from A";
        }
    }

    static class B extends A {
        private final String bString;

        // Before B ever constructed, A constructor will be called.
        // A is invoking a overriden getVar, which is trying to return
        // an initialized bString.
        public B() {                
            bString = "String from B";
        }

        @Override
        public String getVar() {
            return bString;
        }
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        B b = new B();
    }

}

Currently, in my mind, there are two ways to avoid such problem.

Either making class A final class.

static final class A {
    private final String var;

    public A() {
        var = getVar();
        // Null Pointer Exception.
        System.out.println("var string length is " + var.length());
    }

    public String getVar() {
        return "String from A";
    }
}

Or

Making getVar method final

static class A {
    private final String var;

    public A() {
        var = getVar();
        // Null Pointer Exception.
        System.out.println("var string length is " + var.length());
    }

    public final String getVar() {
        return "String from A";
    }
}

The author trying to suggest ways to prevent the above problem. However, the solution seems cumbersome as there are some rules to be followed.

http://benpryor.com/blog/2008/01/02/dont-call-subclass-methods-from-a-superclass-constructor/

Beside making final and the author suggested way, is there more ways to prevent the above problem (Don’t call subclass methods from a superclass constructor) from happen?

like image 320
Cheok Yan Cheng Avatar asked Dec 04 '25 01:12

Cheok Yan Cheng


1 Answers

Making getVar method final

This is definitely what you need to do.

If you're relying on the functionality of a method to initialize an object, you shouldn't let subclasses break that method.

Answering your question, another way to prevent it is to make getVar private in A.

See this simplified version of your code:

// A.java
class A {
    private final String var;
    public A(){
        var = getVar();
        var.length();
    }
    private String getVar(){
        return "This is the value";
    }
}

class B extends A {
    private final String other;
    public B(){
        other = "Other string";
    }
    public String getVar(){
        return other;
    }
}

class Main{
    public static void main( String [] args ) {
        new B();
    }
}

BTW, why did you put those as static nested classes, just to create confusion?

like image 64
OscarRyz Avatar answered Dec 05 '25 14:12

OscarRyz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!