This article is participating in the Java Theme Month – Java Debug Notes Event, see the event link for details

Why must this () and super () be the first statements in the constructor?

Java requires that if you call this () or super () in a constructor, it must be the first statement. Why is that?

Such as:

public class MyClass {
    public MyClass(int x) {}
}

public class MySubClass extends MyClass {
    public MySubClass(int a, int b) {
        int c = a + b;
        super(c);  // COMPILE ERROR
    }
}
Copy the code

The Sun compiler says that “the call to super must be the first statement in the constructor.” The Eclipse compiler says that “the constructor call must be the first statement in the constructor.”

However, you can fix this problem by rearranging some code:

public class MySubClass extends MyClass {
    public MySubClass(int a, int b) {
        super(a + b);  // OK
    }
}
Copy the code

Here’s another example:

public class MyClass {
    public MyClass(List list) {}
}

public class MySubClassA extends MyClass {
    public MySubClassA(Object item) {
        // Create a list that contains the item, and pass the list to super
        List list = new ArrayList();
        list.add(item);
        super(list);  // COMPILE ERROR
    }
}

public class MySubClassB extends MyClass {
    public MySubClassB(Object item) {
        // Create a list that contains the item, and pass the list to super
        super(Arrays.asList(new Object[] { item }));  // OK
    }
}
Copy the code

Therefore, this does not prevent you from executing the logic before calling super. This simply prevents you from executing logic that cannot be contained in a single expression.

The call has a similar rule this(). The compiler says “the call to this must be the first statement in the constructor.”

Why do compilers have these limitations? Can you give an example of code where something bad would happen if the compiler did not have this limitation?

Answer:


A lot of knowledge points, really need to write out will master ! ! !   \color{purple} a lot of knowledge points, really need to write out just can master!! {~}

The parent class constructor needs to be called before the subclass constructor. This ensures that if you call any method on the parent class in the constructor, that parent class is set up correctly.

What you want to do is that passing args to the parent constructor is perfectly legal, you just need to construct these arGs inline at operation time, or pass them to the constructor and then pass them to super:

public MySubClassB extends MyClass { public MySubClassB(Object[] myArray) { super(myArray); }} If the compiler does not force this, you can do the following:  public MySubClassB extends MyClass { public MySubClassB(Object[] myArray) { someMethodOnSuper(); //ERROR super not yet constructed super(myArray); }}Copy the code

If the parent class has a default constructor, the call compiler to super is automatically inserted for you. Because every class in Java inherits from Object, the Object constructor must be called somehow, and it must be executed first. The compiler automatically inserts super () to do this. Enforce super to come first, enforce constructor bodies to be executed in the correct order: Object-> Parent-> Child-> ChildOfChild-> SoOnSoForth

Answer:

Because that’s what JLS says. Can the JLS be changed in a compatible way to allow it? Yes.

However, this complicates the language specification, which is no longer complicated enough. Doing so is not a very useful thing to do, and there are many ways around it (calling another constructor, this(fn(), using a static method or the result of a lambda expression)- this method is called before the other constructor and will therefore be called before the super constructor). Therefore, the power to weight ratio that makes the change is unfavorable.

Note that this rule alone does not prevent the use of fields before the superclass completes 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.
Copy the code

This example is legal, but “wrong”.

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

In the example above, if MyDerived. Fn needs an argument provided by the MyDerived constructor, it needs to be used to select ThreadLocal. ; (

By the way, since Java 1.4, the composite fields containing the outside are allocated before this calls the inner class super constructor. This causes NullPointerException to have a special event in code compiled against earlier versions.

Also note that in the case of unsafe publications, constructs can be reviewed through other threads unless precautions are taken.

Edit March 2018: in message record: construction and validation, Oracle recommends removing this restriction (but unlike C#, absolutely this is not assigned (DU) before the constructor link).

The article translated from kgs4h5t57thfb6iyuz6dqtun5y ac4c6men2g7xr2a – stackoverflow – com. Translate. Goog/questions / 1…

The authors suggest that passing arguments to the constructor of the parent class is fine


Welcome to my column S t a c k O v e r F l o w . I select the best questions and answers and test them frequently in interviews ! ! !   \color{red} Welcome to my column StackOverFlow, I will filter the quality of the interview test!! {~}


There are the latest and elegant ways to do this, and I will write my thoughts on this q&A at the end of the article \color{red} has the latest, elegant implementation, and I will also write my opinion on this question at the end of the article {~}

Thank you for reading this, if this article is well written and if you feel there is something to it

Ask for a thumbs up 👍 ask for attention ❤️ ask for share 👥 for 8 abs I really very useful!!

If there are any mistakes in this blog, please comment, thank you very much! ❤ ️ ❤ ️ ❤ ️ ❤ ️