Java Constructor Inheritance: Understand Constructors in Inheritance

0

If methods can be inherited, it is natural to ask whether constructors can be inherited too. The answer is no. Constructors belong specifically to the class that declares them and are not inherited by subclasses.

However, when a child object is created, the constructor of its parent class is still involved in initializing the parent portion of that object. This distinction is one of the most important ideas to understand when working with inheritance.

Constructors are not inherited, but a parent constructor is invoked during child-object creation so that the inherited part of the object can be initialized.

Why Constructors Are Not Inherited

A constructor is responsible for initializing objects of the class in which it is declared. It has the same name as that class and does not behave like an ordinary inherited method.

class Person {
    Person() {
        System.out.println("Person constructor");
    }
}

class Student extends Person {
}

The Student class does not inherit the Person() constructor. You cannot write code that treats Person() as if it were a constructor of Student.

What does happen, however, is that when a Student object is created, Java ensures that an appropriate parent constructor executes first.

Parent Constructor Executes First

class Person {
    Person() {
        System.out.println("Person constructor");
    }
}

class Student extends Person {
    Student() {
        System.out.println("Student constructor");
    }
}

public class Main {
    public static void main(String[] args) {
        Student student = new Student();
    }
}

The output is:

Person constructor
Student constructor

Even though the child constructor does not explicitly contain a super() call, Java implicitly invokes the accessible no-argument constructor of the immediate parent.

Think of object construction as moving from parent to child: initialize the parent portion first, then initialize the child portion.

Implicit super()

If a child constructor does not explicitly call another constructor using this() or super(), Java inserts a call to the no-argument constructor of the immediate superclass.

class Parent {
    Parent() {
        System.out.println("Parent initialized");
    }
}

class Child extends Parent {
    Child() {
        // Java implicitly inserts super();
        System.out.println("Child initialized");
    }
}

Conceptually, the child constructor behaves as though it were written like this:

class Child extends Parent {
    Child() {
        super();
        System.out.println("Child initialized");
    }
}

When Explicit super() Is Required

Suppose the parent class does not provide an accessible no-argument constructor. In that case, the child must explicitly select one of the available parent constructors.

class Person {
    Person(String name) {
        System.out.println("Name: " + name);
    }
}

class Student extends Person {
    Student(String name) {
        super(name);
    }
}

Here, super(name) explicitly invokes the parameterized constructor of Person. Without it, Java would attempt to insert super(), but no matching parent constructor would exist.

Constructor Chaining Through Multiple Levels

Constructor execution becomes even more interesting with multilevel inheritance. If C extends B and B extends A, creating a C object causes the constructor chain to move through the hierarchy from A to B and finally to C.

class A {
    A() {
        System.out.println("A constructor");
    }
}

class B extends A {
    B() {
        System.out.println("B constructor");
    }
}

class C extends B {
    C() {
        System.out.println("C constructor");
    }
}

public class Main {
    public static void main(String[] args) {
        new C();
    }
}

The output is:

A constructor
B constructor
C constructor

This is called constructor chaining. Each constructor ensures that the class directly above it has been initialized before its own initialization logic runs.

Parameterized Constructor Chaining

Parent constructors can also receive values from child constructors. This is common when different levels of a class hierarchy own different pieces of object state.

class Person {
    String name;

    Person(String name) {
        this.name = name;
    }
}

class Student extends Person {
    int rollNumber;

    Student(String name, int rollNumber) {
        super(name);
        this.rollNumber = rollNumber;
    }
}

public class Main {
    public static void main(String[] args) {
        Student student = new Student("Ravi", 101);
    }
}

The parent constructor initializes name, while the child constructor initializes rollNumber. Each class remains responsible for its own state.

Constructor Overloading in a Child Class

A child class can define multiple constructors of its own. These constructors are not inherited from the parent. Each child constructor must eventually participate in the parent-constructor chain.

class Person {
    Person(String name) {
        System.out.println("Person: " + name);
    }
}

class Student extends Person {

    Student(String name) {
        super(name);
    }

    Student(String name, int rollNumber) {
        super(name);
        System.out.println("Roll: " + rollNumber);
    }
}

The two constructors belong exclusively to Student. They are not inherited versions of the Person constructor.

Constructors and Method Overriding Are Different

A common interview trap is saying that constructors can be overridden. They cannot. Overriding applies to inherited instance methods, while constructors are tied to their declaring class.

Feature Constructor Instance Method
Inherited No Yes, when accessible
Overridden No Yes
Name Must match class name Can have any valid method name
Return type No return type May have a return type
Primary purpose Initialize objects Perform behavior

Private Constructors and Inheritance

A private constructor cannot be directly invoked by a subclass because it is inaccessible outside its declaring class. This can affect whether a class can be extended in a particular way.

class Parent {
    private Parent() {
        System.out.println("Parent");
    }
}

class Child // Cannot extend Parent successfully
{
}

The important lesson is that constructor accessibility matters during subclass construction. A child must be able to invoke an appropriate accessible constructor in the parent chain.

Common Beginner Mistakes

  • Saying that constructors are inherited.
  • Thinking super() means the child inherits the parent's constructor.
  • Forgetting that a parent no-argument constructor must exist and be accessible for an implicit super() call.
  • Trying to override a constructor.
  • Ignoring the parent constructor when designing initialization for a subclass.

Best Practice

Let each constructor initialize the state owned by its class. Use super(...) to pass the required information to the parent, and use this(...) when one constructor in the same class should delegate to another.

This keeps initialization responsibilities clear and makes inheritance hierarchies easier to maintain.

Interview Insight

A strong interview answer is: "Constructors are not inherited or overridden in Java. When a subclass object is created, a constructor from the superclass is invoked first, either explicitly through super(...) or implicitly through super() when an accessible no-argument constructor is available."

Final Takeaway

Constructor inheritance is really about understanding what does not happen: constructors are never inherited. Instead, Java uses constructor chaining to initialize the parent portion of a child object before the child portion. Remember the sequence: parent constructor first, child constructor second. Once this becomes clear, the next topic—how final interacts with inheritance—will show how Java can deliberately prevent further inheritance or method customization.

Post a Comment

0Comments
Post a Comment (0)