Why do this() and super() have to be the first statement in a constructor? Why do this() and super() have to be the first statement in a constructor? java java

Why do this() and super() have to be the first statement in a constructor?


The parent class' constructor needs to be called before the subclass' constructor. This will ensure that if you call any methods on the parent class in your constructor, the parent class has already been set up correctly.

What you are trying to do, pass args to the super constructor is perfectly legal, you just need to construct those args inline as you are doing, or pass them in to your constructor and then pass them to super:

public MySubClassB extends MyClass {        public MySubClassB(Object[] myArray) {                super(myArray);        }}

If the compiler did not enforce this you could do this:

public MySubClassB extends MyClass {        public MySubClassB(Object[] myArray) {                someMethodOnSuper(); //ERROR super not yet constructed                super(myArray);        }}

In cases where a parent class has a default constructor the call to super is inserted for you automatically by the compiler. Since every class in Java inherits from Object, objects constructor must be called somehow and it must be executed first. The automatic insertion of super() by the compiler allows this. Enforcing super to appear first, enforces that constructor bodies are executed in the correct order which would be: Object -> Parent -> Child -> ChildOfChild -> SoOnSoForth


I've found a way around this by chaining constructors and static methods. What I wanted to do looked something like this:

public class Foo extends Baz {  private final Bar myBar;  public Foo(String arg1, String arg2) {    // ...    // ... Some other stuff needed to construct a 'Bar'...    // ...    final Bar b = new Bar(arg1, arg2);    super(b.baz()):    myBar = b;  }}

So basically construct an object based on constructor parameters, store the object in a member, and also pass the result of a method on that object into super's constructor. Making the member final was also reasonably important as the nature of the class is that it's immutable. Note that as it happens, constructing Bar actually takes a few intermediate objects, so it's not reducible to a one-liner in my actual use case.

I ended up making it work something like this:

public class Foo extends Baz {  private final Bar myBar;  private static Bar makeBar(String arg1,  String arg2) {    // My more complicated setup routine to actually make 'Bar' goes here...    return new Bar(arg1, arg2);  }  public Foo(String arg1, String arg2) {    this(makeBar(arg1, arg2));  }  private Foo(Bar bar) {    super(bar.baz());    myBar = bar;  }}

Legal code, and it accomplishes the task of executing multiple statements before calling the super constructor.


Because the JLS says so. Could the JLS be changed in a compatible manner to allow it? Yup.

However, it would complicate the language spec, which is already more than complicated enough. It wouldn't be a highly useful thing to do and there are ways around it (call another constructor with the result of a static method or lambda expression this(fn()) - the method is called before the other constructor, and hence also the super constructor). So the power to weight ratio of doing the change is unfavourable.

Note that this rule alone does not prevent use of fields before the super class has completed construction.

Consider these illegal examples.

super(this.x = 5);super(this.fn());super(fn());super(x);super(this instanceof SubClass);// this.getClass() would be /really/ useful sometimes.

This example is legal, but "wrong".

class MyBase {    MyBase() {        fn();    }    abstract void fn();}class MyDerived extends MyBase {    void fn() {       // ???    }}

In the above example, if MyDerived.fn required arguments from the MyDerived constructor they would need to be sleazed through with a ThreadLocal. ;(

Incidentally, since Java 1.4, the synthetic field that contains the outer this is assigned before inner classes super constructor is called. This caused peculiar NullPointerException events in code compiled to target earlier versions.

Note also, in the presence of unsafe publication, construction can be viewed reordered by other threads, unless precautions are made.

Edit March 2018: In message Records: construction and validation Oracle is suggesting this restriction be removed (but unlike C#, this will be definitely unassigned (DU) before constructor chaining).

Historically, this() or super() must be first in a constructor. This restriction was never popular, and perceived as arbitrary. There were a number of subtle reasons, including the verification of invokespecial, that contributed to this restriction. Over the years, we've addressed these at the VM level, to the point where it becomes practical to consider lifting this restriction, not just for records, but for all constructors.