Skip to content

Calling Superclass Constructor

When a subclass object is created, it implicitly calls the constructor of its superclass to ensure proper initialization of the inherited properties. In Java, you can explicitly call the superclass constructor using the super keyword. This feature allows you to control which constructor of the superclass gets invoked.


Key Points

  1. Default Behavior:
    1. If no explicit call to a superclass constructor is made, Java automatically inserts a call to the default constructor of the superclass (super()).
    1. If the superclass does not have a no-argument constructor, you must explicitly call a specific constructor of the superclass.
  2. Explicit Call Using super:
    1. The super keyword can be used to call a specific constructor of the superclass.
    1. Must be the first statement in the subclass constructor.
  3. Access Modifiers:
    1. The superclass constructor must be accessible in the subclass (e.g., public or protected).

Example of Implicit Constructor Call

class Parent {

    Parent() {

        System.out.println(“Parent class constructor called.”);

    }

}

class Child extends Parent {

    Child() {

        System.out.println(“Child class constructor called.”);

    }

}

public class Main {

    public static void main(String[] args) {

        Child child = new Child();

    }

}

Output:

Parent class constructor called.

Child class constructor called.

Here, super() is implicitly invoked in the Child constructor.


Example of Explicit Constructor Call Using super

class Parent {

    Parent(String message) {

        System.out.println(“Parent class constructor: ” + message);

    }

}

class Child extends Parent {

    Child() {

        super(“Hello from Parent!”); // Explicit call to superclass constructor

        System.out.println(“Child class constructor called.”);

    }

}

public class Main {

    public static void main(String[] args) {

        Child child = new Child();

    }

}

Output:

Parent class constructor: Hello from Parent!

Child class constructor called.


Using super to Call Parameterized Constructors

If the superclass has multiple constructors, you can specify which one to call by providing the appropriate arguments.

Example:

class Parent {

    Parent() {

        System.out.println(“Parent default constructor.”);

    }

    Parent(String message) {

        System.out.println(“Parent constructor with message: ” + message);

    }

}

class Child extends Parent {

    Child(String message) {

        super(message); // Calls parameterized constructor of Parent

        System.out.println(“Child constructor with message: ” + message);

    }

}

public class Main {

    public static void main(String[] args) {

        Child child = new Child(“Hello from Child!”);

    }

}

Output:

Parent constructor with message: Hello from Child!

Child constructor with message: Hello from Child!


Chaining with Multiple Levels of Inheritance

When there are multiple levels of inheritance, constructors in the hierarchy are called in a top-down manner.

Example:

class Grandparent {

    Grandparent() {

        System.out.println(“Grandparent constructor called.”);

    }

}

class Parent extends Grandparent {

    Parent() {

        super(); // Calls Grandparent constructor

        System.out.println(“Parent constructor called.”);

    }

}

class Child extends Parent {

    Child() {

        super(); // Calls Parent constructor

        System.out.println(“Child constructor called.”);

    }

}

public class Main {

    public static void main(String[] args) {

        Child child = new Child();

    }

}

Output:

Grandparent constructor called.

Parent constructor called.

Child constructor called.


Constructor Overloading with super

A subclass can use overloaded constructors in the superclass for various initialization scenarios.

Example:

class Parent {

    Parent() {

        System.out.println(“Parent default constructor.”);

    }

    Parent(int number) {

        System.out.println(“Parent constructor with number: ” + number);

    }

}

class Child extends Parent {

    Child() {

        super(42); // Call overloaded constructor of Parent

        System.out.println(“Child constructor called.”);

    }

}

public class Main {

    public static void main(String[] args) {

        Child child = new Child();

    }

}

Output:

Parent constructor with number: 42

Child constructor called.


Key Rules for Calling Superclass Constructors

  1. First Statement:
    1. The call to super() or super(arguments) must be the first statement in the subclass constructor.
    1. Failing to do so results in a compilation error.
  2. No Implicit Call if super is Explicitly Used:
    1. If you explicitly call a superclass constructor using super(), Java does not insert an implicit super() call.
  3. Constructor Accessibility:
    1. The superclass constructor must be accessible to the subclass based on its access modifier.
  4. No Superclass Default Constructor:
    1. If the superclass has no default constructor, the subclass constructor must explicitly call a parameterized constructor of the superclass.

Example of Compilation Error

class Parent {

    Parent(String message) {

        System.out.println(“Parent constructor with message: ” + message);

    }

}

class Child extends Parent {

    Child() {

        // Implicit super() is inserted here, but Parent has no default constructor

        System.out.println(“Child constructor called.”);

    }

}

public class Main {

    public static void main(String[] args) {

        Child child = new Child();

    }

}

Error:

Error: constructor Parent in class Parent cannot be applied to given types;


Best Practices

  1. Use super explicitly when the superclass does not have a no-argument constructor or when specific initialization is required.
  2. Ensure the constructor chaining (using super) is meaningful and logically correct.
  3. Minimize complex constructor hierarchies to improve code readability.

Conclusion

Calling a superclass constructor using super is a powerful feature in Java that ensures proper initialization of inherited members. It allows developers to maintain modular, reusable, and clean code while working with class hierarchies. By following Java’s rules for constructor calls, you can effectively manage initialization in complex inheritance scenarios.