user3663882
user3663882

Reputation: 7367

Calling virtual method from a constructor

Java 8

I was just a little perplexed by that we could not call virtual method from a constructor. The pitfall is that we can overload it and crash. But what if we call it from within a constructor of a final class. Like this:

public final class MyClass implements MyInterface {
    private final Object[] arr;
    public MyClass(){
        Object[] arr;
        //init arr
        this.arr = arr;
        //Now we have to preprocess it
        preprocess();
    }

    @Override
    public void preprocess(){
        //impl
    }

    public int count(){
        //impl
    }
}

public interface MyInterface{
    void preprocess();
    int count();
}

Are there other pitfalls with calling virtual methods from within a constructor? Of course, I can extract preprocess into a static method and then call it from both, but it looks a little messy. I'd like to keep code as clean as possible.

Upvotes: 1

Views: 334

Answers (1)

Andreas
Andreas

Reputation: 159185

You should always take care when calling methods from a constructor, because the object construction is not yet complete. This is true even for final and private methods, which cannot be overridden by subclasses.

Example:

public class Test {
    public static void main(String[] args) {
        new Sub().test();
    }
}
class Base {
    int b;
    Base() {
        test();
        this.b = 1;
    }
    void test() {
        System.out.println("Hello from Base. b = " + this.b);
    }
}
class Sub extends Base {
    int s;
    Sub() {
        test();
        this.s = 2;
    }
    @Override
    void test() {
        System.out.println("Hello from Sub. b = " + this.b + ", s = " + this.s);
    }
}

OUTPUT

Hello from Sub. b = 0, s = 0
Hello from Sub. b = 1, s = 0
Hello from Sub. b = 1, s = 2

test() is called 3 times: From Base constructor, from Sub constructor, and from main().

As you can see, even field b was not yet initialized on the first call.

So, is it illegal to do it? No.
Should you avoid it? Yes.
Just make it clear (e.g. javadoc) that the method may be called on partially initialized objects.

Upvotes: 4

Related Questions