Ernestas Gruodis
Ernestas Gruodis

Reputation: 8787

Overridable method call in constructor - what is the proper way to call the method?

What is the difference between these two calls? How should this be done properly?

//package test;

public class SomeClass {

    public SomeClass() {

        doSomething();//Warning - Overridable method call in constructor
        SomeClass.this.doSomething();//Seems OK
    }

    public void doSomething() {
        //...
    }
}

I want to use doSomething() just for convenience in the same class. I have no intentions to override it later. One idea is to declare it final. But still it is not clear if SomeClass.this.doSomething(); is safe to use in this situation.

Upvotes: 0

Views: 2395

Answers (1)

Luiggi Mendoza
Luiggi Mendoza

Reputation: 85789

The compiler warning notification somewhat says what can happen. If a subclass overrides the doSomething method, it can change the behavior when creating the class instance, which may be dangerous or not, depending on your design. Note that it's a warning, not a compiler exception.

To prove this, just extended your code to test it:

class SomeClass {

    public SomeClass() {

        doSomething();//Warning - Overridable method call in constructor
        SomeClass.this.doSomething();//Seems OK, but is not
    }

    public void doSomething() {
        System.out.println("parent");
    }
}

public class SomeOtherClass extends SomeClass {
    @Override
    public void doSomething() {
        System.out.println("child");
    }

    public static void main(String[] args) {
        SomeClass a = new SomeClass();
        SomeOtherClass b = new SomeOtherClass();
    }
}

Prints:

parent
parent
child
child

If you just want that no other class can override doSomething method, mark it as final:

class SomeClass {

    public SomeClass() {

        doSomething();//Warning - Overridable method call in constructor
        SomeClass.this.doSomething();//Seems OK
    }

    public final void doSomething() {
        System.out.println("parent");
    }
}

Then if any subclass tries to override it, the compiler will throw an error:

public class SomeOtherClass extends SomeClass {
    @Override
    public void doSomething() { //compiler error
        System.out.println("child");
    }
    //...
}

Upvotes: 2

Related Questions