OOP Basics ·
‹ Previous Next ›
⏱ 5 min read Modified: 2026-08-02

The super Keyword in Java

You add a parameterized constructor to a parent class called Box, touch nothing else, and the build breaks in three subclasses you never opened: there is no default constructor available in Box. The culprit is an invocation you never wrote — the super() call that the compiler silently inserts as the first statement of every constructor.

The super keyword in Java is a reference to the immediate superclass (parent class) of the current object. It has two jobs: calling a constructor of the superclass with super(...), and reaching a field or method of the superclass that is hidden or overridden in the subclass with super.member.

1. What the super keyword is

super is the inheritance twin of the this keyword. The distinction is simple: this refers to the current object, while super refers to the part of that object which came from the parent class.

A superclass (also called the parent class or the base class) is the class your class extends. In class HeavyBox extends Box, Box is the superclass and HeavyBox is the subclass.

The keyword comes in exactly two forms:

  1. A superclass constructor invocation. Parentheses follow the keyword and carry the argument list:
    super(argumentList);
  2. Access to a member of the superclass that is hidden or overridden in the subclass:
    super.member;

2. Calling the superclass constructor with super()

Passing arguments up the hierarchy

When a class hierarchy needs constructor arguments, every subclass has to forward those values upward. In practice that means calling the superclass constructor with super(...) from the subclass constructor.

Here the constructor of HeavyBox calls the constructor of Box and hands it the three dimensions:

public class Box {
    double width;
    double height;
    double depth;

    Box(double w, double h, double d) {
        width = w;
        height = h;
        depth = d;
    }

    public Box() {
    }
}
public class HeavyBox extends Box {
    int weight;

    public HeavyBox(int width, int height, int depth, int weight) {
        super(width, height, depth);
        this.weight = weight;
    }

    public HeavyBox() {
        this.weight = -1;
    }
}

The second constructor of HeavyBox contains no explicit super() call, so the compiler adds one as the first statement:

public HeavyBox() {
    super();          // inserted by the compiler
    this.weight = -1;
}

That leads to a rule worth memorizing: the superclass needs a no-argument constructor, otherwise the implicit super() has nothing to bind to and the code does not compile.

Important

The implicit super() is inserted by the compiler, not by the JVM — which is why the problem surfaces at build time. Delete the no-argument constructor from Box and javac answers with there is no default constructor available in Box. Remember that as soon as you declare any constructor of your own, the default constructor is no longer generated for you.

Constructor order in a multi-level hierarchy

A super() call always runs the constructor of the immediate superclass, and that holds at every level of a deeper hierarchy. Consider three classes:

Class hierarchy in Java: SuperSuperClass, SuperClass and SomeClass

SuperSuperClass is extended by SuperClass, which in turn is extended by SomeClass. Each constructor does nothing but print its own name:

public class SuperSuperClass {
    public SuperSuperClass() {
        System.out.println("In the SuperSuperClass constructor");
    }
}

public class SuperClass extends SuperSuperClass {
    public SuperClass() {
        System.out.println("In the SuperClass constructor");
    }
}

public class SomeClass extends SuperClass {
    public SomeClass() {
        System.out.println("In the SomeClass constructor");
    }
}

Now create an instance of SomeClass:

SomeClass someClass = new SomeClass();

Program output:

In the SuperSuperClass constructor
In the SuperClass constructor
In the SomeClass constructor

You asked for a SomeClass object, yet the SuperSuperClass constructor ran first, then SuperClass, and only then SomeClass. The chain of implicit super() calls explains it: each constructor first passes control upward, all the way to the root of the hierarchy (ultimately java.lang.Object), and the constructor bodies execute on the way back down, from ancestor to descendant. The reasoning is practical — by the time a subclass constructor body starts, the inherited part of the object is already fully initialized.

3. Statements before super(): flexible constructor bodies

Historically the super() call had to be the first statement of the constructor. Before Java 22 this did not compile:

public class SomeClass extends SuperClass {
    public SomeClass() {
        System.out.println("In the SomeClass constructor"); // compile error before Java 22
        super();
    }
}

The restriction came from the same principle: the superclass part must be built first. In practice it proved stricter than necessary, and developers had to hide argument validation and preparation inside static helper methods.

The rule was relaxed step by step:

Java version JEP Name Status
Java 22 JEP 447 Statements before super(...) Preview (needs --enable-preview)
Java 23 JEP 482 Flexible Constructor Bodies Second preview
Java 24 JEP 492 Flexible Constructor Bodies Third preview
Java 25 JEP 513 Flexible Constructor Bodies Final feature, no flag required

What changed in modern Java

Since Java 25 flexible constructor bodies are an ordinary part of the language. On the LTS releases still running most production systems — Java 17 and Java 21 — the classic rule applies: super() or this() must be the first line of the constructor. Targeting 17 or 21? Move the argument preparation into a private static method and call it right inside super(...). Interviewers usually expect the classic rule too, so state which version you are talking about.

Constructor prologue and epilogue

A constructor body now splits into two parts:

  • the prologue — everything before the super() or this() call;
  • the epilogue — everything after it (or the whole body when there is no explicit call).

The governing rule for the prologue: you cannot touch the object under construction yet, because it does not exist in a usable state.

In the prologue Allowed Not allowed
Fields of the current class Assigning a value (this.x = 1;) Reading a value
Inherited fields Neither reading nor writing
Methods Calling static methods Calling instance methods
The this reference Only on the left of = when assigning to a field Passing it around or returning it
Nested classes Referring to members of the outer class Creating non-static inner classes
Local computation Anything: checks, loops, throw

Case 1. Validating arguments

Back to HeavyBox. The width has to be positive: if it is zero or negative there is no point in building the object, so the exception is thrown before the parent constructor runs.

public HeavyBox(int width, int height, int depth, int weight) {
    if (width <= 0) {
        throw new IllegalArgumentException("width must be positive");
    }
    super(width, height, depth);
    this.weight = weight;
}

Case 2. Preparing arguments

Suppose every dimension must be doubled before it reaches the superclass constructor:

public HeavyBox(int width, int height, int depth, int weight) {
    width *= 2;
    height *= 2;
    depth *= 2;
    super(width, height, depth);
    this.weight = weight;
}

Case 3. Reusing one object in several arguments

Say Box has a constructor that takes two Point objects:

public class Box {
    // ...
    public Box(Point p1, Point p2) {
    }
    // ...
}

With no code allowed before super(), you have to create two separate objects (or accept them from outside):

public HeavyBox() {
    super(new Point(), new Point());
}

With a flexible constructor body one object is enough, and it can be passed twice:

public HeavyBox() {
    Point p = new Point();
    super(p, p);
}

4. Accessing superclass fields and methods

The second form, super.member, gives a subclass access to a field or method of its parent. Most of the time you do not need it: inherited members are already visible by their plain names. It becomes necessary only when the name is shadowed in the subclass.

Class C declares an int field named i. Its subclass D declares a field with the same name but of type String. (A warning up front: never write code like this in production — the example exists only to show the mechanics.) Inside D the plain name i resolves to String i, which hides int i. Reaching the inherited field requires super.i.

Methods work the same way. Both classes define print(), so calling the parent implementation from D takes super.print().

public class C {
    public int i;

    public void print() {
        System.out.println("C.i = " + i);
    }
}

public class D extends C {
    public String i;

    public D(String a, int b) {
        i = a;
        super.i = b;
    }

    public void print() {
        System.out.println("D.i = " + i);
        super.print();
    }
}

public class UseSuperExample {
    public static void main(String[] args) {
        D d = new D("someString", 2);
        d.print();
        System.out.println(d.i);
    }
}

Program output:

D.i = someString
C.i = 2
someString

Note the asymmetry between fields and methods. Fields are hidden and resolved by the static type of the reference, while methods are overridden and resolved by the actual type of the object. That is exactly why super.print() is the only way to reach the parent version from inside an override: a plain print() call inside D would dispatch back to D.print() and recurse forever.

Remember

super is not an object and not a reference you can store: Object o = super; does not compile. It is a special access form that the compiler turns into a non-virtual call — the invokespecial bytecode instruction — and that is precisely why super.print() does not recurse into the override.

5. super, super(), this and this(): the difference

Four look-alike constructs that interviewers love to mix up:

Construct What it does Where you can use it Typical use
super(...) Calls a constructor of the superclass Only in a constructor, once super(width, height, depth);
this(...) Calls another constructor of the same class Only in a constructor, once this(0, 0, 0, 0);
super.member Reaches a hidden field or an overridden method of the parent In any instance method and in a constructor super.print();
this.member Reaches a field or method of the current object In any instance method and in a constructor this.weight = weight;

The key constraint: super(...) and this(...) are mutually exclusive — a single constructor may contain only one of them. When a constructor starts with this(...), the superclass constructor is invoked further along the chain, inside the constructor you delegated to.

6. What people get wrong about super

  • The parent lost its no-argument constructor. You add a parameterized constructor to the superclass, and every subclass that relied on the implicit super() stops compiling — the failure shows up in files you never edited.
  • super in a static context. Neither super nor this exists in a static method or a static initializer block: there is no object yet.
  • Calling an overridable method from a constructor. If a superclass constructor calls a method that the subclass overrides, the override runs before the subclass fields are initialized and sees null or 0. Declare such methods final or private.
  • Writing super.super.method(). Java forbids that syntax outright: you cannot skip a level of the hierarchy.
  • Predicting log order backwards. Constructor bodies run from the root of the hierarchy down to the leaf, not the other way round — a classic interview trap.

The formal rules for constructor invocations live in the language specification: JLS, section 8.8.7 Constructor Body.

Frequently asked questions

Can a constructor call both super() and this()?

No. A constructor may contain exactly one explicit invocation — either super(...) or this(...). When you write this(...), the compiler does not add an implicit super(): the superclass constructor runs inside the constructor you delegated to. Either way, the chain ends up performing exactly one super(...) call per object.

Why doesn't super.super.method() work?

The Java Language Specification forbids it. A class only has a contract with its immediate parent, and being able to bypass that parent's implementation would break encapsulation. If you genuinely need the grandparent behaviour, add a bridge method in the intermediate class that calls super.method() and expose it under a different name.

How do I call an interface default method that my class overrides?

Use the qualified form InterfaceName.super.method(), for example Walkable.super.move(). It works only for interfaces the class implements directly, and it is the standard way out when two interfaces supply conflicting default implementations of the same method.

Can I use super in a static method?

No. Both super and this are tied to a specific instance, and a static method runs without one, so the code does not compile. To reach a static member of the parent, qualify it with the class name instead: Box.someStaticMethod().

What does "there is no default constructor available" mean?

The compiler tried to insert an implicit super() into a subclass constructor, but the superclass has no no-argument constructor. That happens as soon as the parent declares at least one constructor of its own, because the default constructor is then no longer generated. Fix it by adding a no-argument constructor to the parent or by calling an existing one explicitly with super(...).

Summary

  • super refers to the immediate superclass: super(...) invokes its constructor, super.member reaches its field or method.
  • With no explicit call, the compiler inserts super() as the first statement — so the parent must have a no-argument constructor.
  • Constructor bodies execute from the root of the hierarchy down to the current class, never the other way round.
  • super.member is needed only when the name is hidden or overridden in the subclass.
  • Statements before super() are allowed from Java 25 onward (JEP 513); on Java 17 and 21 the superclass constructor call must still come first.

Comments

Please log in or register to have a possibility to add comment.