Can a java subclass's private final field be initialized before the super constructor completes?

前端 未结 3 1772
感动是毒
感动是毒 2021-01-23 03:58

I have a pair of classes looking like this;

public abstract class Class1 {

//...

    public Class1() {
        //...
        function2();
        //...
    }

         


        
3条回答
  •  小鲜肉
    小鲜肉 (楼主)
    2021-01-23 04:59

    Short answer - no. A superclass' constructor, field initialisers and instance initialisers are always called before the subclass'.

    The order of calls is formally defined in section 8.8.7.1 of the JLS. Summarising the relevant last parts (where S is the superclass and C is the subclass):

    After determining the immediately enclosing instance of i with respect to S (if any), evaluation of the superclass constructor invocation statement proceeds by evaluating the arguments to the constructor, left-to-right, as in an ordinary method invocation; and then invoking the constructor.

    Finally, if the superclass constructor invocation statement completes normally, then all instance variable initializers of C and all instance initializers of C are executed. If an instance initializer or instance variable initializer I textually precedes another instance initializer or instance variable initializer J, then I is executed before J.

    So when the superclass constructor runs, the subclass and all its fields are completely uninitialised. It's bad practice to call overridden methods from a constructor for this reason. You're essentially letting a reference to the object "escape" from its constructor, which means all the guarantees of construction are off (including things like final fields changing value, etc.).

    Calling an abstract method from a constructor is almost always the wrong thing to do. Depending on the implementation of the method in the subclass(es) you might get away with it in some case (i.e. if the method does not depend on any state at all), but it will almost certainly cause a hard-to-debug failure at some point.

    For example, would you expect there to be a difference between:

    protected String function2() {
        return "foo";
    }
    

    and

    private final String foo = "foo";
    
    protected String function2() {
        return foo;
    }
    

    Analysing problems like this is hard, because they break the mental model of how classes work. Best to avoid this situation altogether.

提交回复
热议问题