Leepoint Java Reference Notes on the Java language and its standard library.

Calling the superclass constructor

The parent is always constructed first, whether or not you say so.

Before a subclass constructor body runs, the superclass constructor must complete. You can say which one:

public class Circle extends Shape {
    private final double radius;

    public Circle(String name, double radius) {
        super(name);
        this.radius = radius;
    }
}

super(...) must be the first statement. So must this(...), which is why you cannot have both, a constructor delegates either sideways or upwards, never both.

The invisible super()

Omit it and the compiler inserts super(). The no-argument superclass constructor.

That is fine until the parent does not have one:

public class Shape {
    Shape(String name) { ... }      // no no-arg constructor
}

public class Circle extends Shape {
    Circle() { }                    // won't compile
}

The error message talks about an implicit super() that does not exist. The fix is to call the constructor that does:

Circle() { super("circle"); }

This is the usual reason a subclass suddenly stops compiling after someone adds a constructor to the parent. Adding any constructor removes the free no-argument one.

Order of initialisation

For new Circle(...):

  1. Object’s constructor, then each ancestor down the chain
  2. The superclass’s field initialisers and instance blocks
  3. The superclass constructor body
  4. The subclass’s field initialisers
  5. The subclass constructor body

Field initialisers run after the parent constructor, which is the trap below.

Why not to call overridable methods

class Shape {
    Shape() { draw(); }             // overridable
    void draw() { }
}

class Circle extends Shape {
    private double radius = 5;
    @Override void draw() { System.out.println(radius); }
}

new Circle() prints 0.0. The parent constructor calls draw(), the subclass override runs, and radius has not been initialised yet, step 3 happens before step 4.

Make anything a constructor calls private, final or static.

super outside constructors

super.method() calls the parent’s version. The usual way to extend rather than replace behaviour:

@Override
public String toString() {
    return super.toString() + " radius=" + radius;
}