3 Statements Before super(…)
In constructors, you may add statements that don't reference the instance being created before an explicit constructor invocation.
Note:
This is a preview feature. A preview feature is a feature whose design, specification, and implementation are complete, but is not permanent. A preview feature may exist in a different form or not at all in future Java SE releases. To compile and run code that contains preview features, you must specify additional command-line options. See Preview Language and VM Features.For background information about statements before
                    super(...), see JEP 447.
                  
You can use this feature to prepare arguments for a superclass constructor
            by performing nontrivial computations or validate arguments you want to pass to a
            superclass constructor. The following example validates whether the argument
                value is positive before passing it to the superclass
            constructor:
               
public class PositiveBigInteger extends BigInteger {
    public PositiveBigInteger(long value) {
        if (value <= 0)
            throw new IllegalArgumentException("non-positive value");
        super(Long.toString(value));
    }
}The prologue of the constructor's body consists of the statements that appear
            before the super(...) invocation. The epilogue of the
            constructor's body consists of the statements that follow the
                super(...) invocation.
               
The Preconstruction Context of a Constructor
The preconstruction context of a constructor consists of the
        arguments to an explicit constructor invocation, such as super(...), and
        any statements before it.
                  
In the previous example the preconstruction context of
                PositiveBigInteger consists of the argument value,
            and the if-statement that checks whether value is
            positive.
                  
Code in a preconstruction context may not access the instance under construction. This means you can’t have the following in a preconstruction context:
- 
                        
                        Any unqualified thisexpression: Note that you don't need to use thethiskeyword to access the instance under construction. For example:class A { int i; A() { // Error: Cannot reference this before supertype constructor has been // called this.i++; // Error: cannot reference i before supertype constructor has been // called i++; // Error: cannot reference this before supertype constructor has been // called this.hashCode(); // Error: cannot reference hashCode() before supertype constructor has // been called hashCode(); // Error: cannot reference this before supertype constructor has been // called System.out.print(this); super(); } }
- 
                        
                        Any field access, method invocation, or method reference qualified by super: Again, note that you don't need to use thesuperkeyword to access the superclass of the instance under construction:class D { int j; } class E extends D { E() { // Error: cannot reference super before supertype constructor has been called super.j++; // Error: cannot reference j before supertype constructor has been // called j++; super(); } }
Nested Classes
A nested class is a member of its enclosing class, which means you can't access a nested class from its enclosing class's preconstruction context. For example:
class B {
    
    class C { }
    
    B() {
        // Error: cannot reference this before supertype constructor has been
        //        called
        new C();
        super();
    }
}However, a nested class's enclosing class is not one of its
                members, which means you can access its enclosing class from its preconstruction
                context. In the following example, both accessing F's member
                variable f and method hello() in the
                preconstruction context of its nested class G is permitted:
                     
class F {
    
    int f;
    
    void hello() {
        System.out.println("Hello!");
    }
    
    class G {
        G() {
            F.this.f++;
            hello();
            super();
        }
    }
}Records
Record constructors may not invoke super(...). However, noncanonical
                constructors must involve a canonical constructor by invoking
                    this(...). Statements may appear before
                    this(...).
                     
Remember that a canonical constructor is a constructor whose signature is the same as the record's component list. It initializes all the component fields of the record class. Alternative or noncanonical record constructors have argument lists that don't match the record's type parameters.
In the following example, the record RectanglePair contains a
                noncanonical constructor, RectanglePair(Pair<Float> corner).
                Because it's a noncanonical constructor, it must invoke a canonical constructor with
                    this(...). It contains several statements before
                    this(...) that retrieve both values from the
                    Pair<Float> parameter and validate that these values aren't
                negative:
                     
record Pair<T extends Number>(T x, T y) { }
record RectanglePair(float length, float width) {
    public RectanglePair(Pair<Float> corner) {
        float x = corner.x().floatValue();
        float y = corner.y().floatValue();
        if (x < 0 || y < 0) {
            throw new IllegalArgumentException("non-positive value");
        }
        this(corner.x().floatValue(), corner.y().floatValue());
    }
}See Alternative Record Constructors in Record Classes for more information.