8.2 Inheritance Fundamentals and the super Keyword

Key Takeaways

  • Inheritance establishes an 'is-a' relationship using the extends keyword, enabling a subclass to acquire and reuse accessible members from a superclass.
  • Java enforces a strict single class inheritance model where a class can directly extend at most one superclass, with java.lang.Object serving as the root of all classes.
  • Subclasses inherit public and protected members (and package-private members in the same package), but never inherit private members or superclass constructors.
  • Constructor chaining requires invoking a superclass constructor via super(...), which must be the very first statement; if omitted, the compiler automatically inserts super().
  • If a superclass defines only parameterized constructors without a no-argument constructor, subclass constructors must explicitly call super(...) with matching arguments to avoid compile-time errors.
Last updated: September 2026

8.2 Inheritance Fundamentals and the super Keyword

[!NOTE] Exam Focus: Inheritance is one of the most heavily tested themes behind Oracle's "describe the components of object-oriented programming" objective. Candidates must thoroughly understand the syntax and semantics of the extends keyword, Java's single inheritance constraint, the universal java.lang.Object class hierarchy, what members are inherited versus not inherited, constructor chaining execution order, and the compilation errors caused when a parent class lacks a no-argument constructor.

Inheritance is an essential object-oriented programming mechanism that allows a new class to acquire properties (fields) and behaviors (methods) from an existing class. The class that supplies the inherited members is termed the superclass (or base class / parent class), while the class that inherits those members is termed the subclass (or derived class / child class).

Inheritance models the foundational "is-a" relationship:

  • A Car is-a Vehicle
  • An HourlyEmployee is-a Employee
  • A CheckingAccount is-a BankAccount

This contrasts sharply with composition, which models the "has-a" relationship (for example, a Car has-an Engine, or a BankAccount has-a TransactionHistory).


1. The extends Keyword and Code Reuse

In Java, inheritance is declared using the extends keyword in the class definition header:

// Superclass
public class Vehicle {
    private String registrationNumber;
    protected int maximumSpeed;

    public void startEngine() {
        System.out.println("Vehicle engine started.");
    }

    public void stopEngine() {
        System.out.println("Vehicle engine stopped.");
    }
}

// Subclass extending Vehicle
public class Car extends Vehicle {
    private int numberOfDoors;

    public void openTrunk() {
        System.out.println("Trunk opened.");
    }
}

When Car extends Vehicle, an instance of Car automatically acquires the accessible members of Vehicle. Client code can instantiate Car and invoke both superclass and subclass behaviors:

Car sedan = new Car();
sedan.startEngine(); // Inherited from Vehicle
sedan.openTrunk();   // Defined directly in Car
sedan.stopEngine();  // Inherited from Vehicle

By leveraging inheritance, developers avoid duplicate code across related classes, centralize common business logic in superclasses, and create structured hierarchies that simplify system maintenance.


2. Java's Single Inheritance Model and java.lang.Object

Java enforces two fundamental architectural rules across its class inheritance model:

1. Single Class Inheritance

A Java class can directly extend at most one direct superclass. Java does not support multiple class inheritance:

// COMPILE ERROR: Syntax error, multiple inheritance of classes is forbidden in Java
public class HybridVehicle extends GasolineCar, ElectricCar { 
}

Java disallows multiple class inheritance to prevent the notorious Diamond Problem, where ambiguities arise when two parent classes define conflicting implementations of the exact same method or maintain duplicate internal state.

2. The Universal Root Class: java.lang.Object

Every single class in the Java programming language is a direct or indirect descendant of java.lang.Object (located in the java.lang package). If a class declaration does not contain an explicit extends clause, the Java compiler automatically inserts extends java.lang.Object into the compiled bytecode:

// You write:
public class Book {
}

// The Java compiler generates:
public class Book extends java.lang.Object {
}

Because Object sits at the root of the entire class hierarchy, every Java object inherits foundational methods defined in Object:

  • toString(): Returns a String representation of the object (by default, ClassName@HexHashCode).
  • equals(Object obj): Tests whether two references point to the exact same object in memory (reference equality).
  • hashCode(): Returns an integer hash code value for the object.
  • getClass(): Returns the runtime Class object representing the entity.

Transitive Inheritance

Inheritance in Java is transitive. If class ElectricCar extends Car, and Car extends Vehicle, then ElectricCar is an indirect subclass of both Vehicle and Object. An ElectricCar instance possesses all inherited members from Car, Vehicle, and Object.


3. Member Inheritance: What Is Inherited and What Is Not

A critical area tested on the 1Z0-811 examination is determining exactly which components of a superclass are inherited by a subclass.

What Subclasses Inherit

  1. public members: Inherited by all subclasses regardless of package location.
  2. protected members: Inherited by all subclasses in any package.
  3. Default / Package-private members: Inherited by subclasses only if the subclass resides in the exact same package as the superclass.

What Subclasses DO NOT Inherit

  1. private Members Are NOT Inherited:
    • A subclass does not inherit private fields or private methods of its superclass.
    • Physical Memory Nuance: When a subclass object is instantiated on the Java Heap, memory is allocated for all fields declared across the entire inheritance hierarchy, including private fields from parent classes! However, code inside the subclass cannot reference those private fields directly by identifier. The subclass can only interact with them indirectly through inherited public or protected accessor/mutator methods.
  2. Constructors Are NOT Members and Are NEVER Inherited:
    • Constructors are special initialization blocks responsible for constructing instances of their declaring class. They are never inherited by subclasses.
    • A subclass must declare its own constructors, which chain to superclass constructors.
  3. Initialization Blocks Are NOT Inherited:
    • Static and instance initialization blocks run during class loading and object construction, but they are not callable members and are not inherited.

4. Constructor Chaining and the super(...) Keyword

When a subclass object is instantiated using the new operator, the subclass constructor does not run in isolation. Because the subclass object incorporates all instance variables of its superclasses, the superclass constructor must execute first to initialize the inherited state before the subclass constructor performs its own initialization.

This sequential invocation of constructors through the inheritance hierarchy is known as constructor chaining.

Invoking Superclass Constructors via super(...)

A subclass constructor explicitly delegates to a superclass constructor using the super(...) statement:

public class Person {
    private String name;

    public Person(String name) {
        this.name = name;
        System.out.println("1. Person constructor executed for: " + name);
    }
}

public class Student extends Person {
    private int studentId;

    public Student(String name, int studentId) {
        super(name); // Explicit call to superclass constructor
        this.studentId = studentId;
        System.out.println("2. Student constructor executed for ID: " + studentId);
    }
}

When executing Student s = new Student("Alice", 1001);, the console outputs:

1. Person constructor executed for: Alice
2. Student constructor executed for ID: 1001

Strict Rules for super(...) in Constructors

[!IMPORTANT] The First Statement Rule: If a constructor contains an explicit call to super(...) or this(...), that call MUST be the very first executable statement in the constructor body. Placing any code, variable assignment, or print statement prior to super(...) triggers an immediate compile-time error:

public Student(String name, int studentId) {
    System.out.println("Starting initialization...");
    super(name); // COMPILE ERROR: call to super must be first statement in constructor
}
  1. Mutually Exclusive: A constructor body can invoke super(...) OR this(...), but never both in the same constructor body, because both demand the first statement position.
  2. Implicit super(); Insertion: If a constructor body contains neither an explicit call to super(...) nor a call to this(...), the Java compiler automatically inserts an implicit super(); (with zero arguments) as the very first line.

5. The "Missing Default Constructor" Trap (Signature 1Z0-811 Trap!)

The most pervasive inheritance pitfall on the 1Z0-811 examination arises from the interaction between compiler-generated default constructors and subclass constructor chaining.

Recall the compiler constructor rule: The Java compiler generates a default no-argument constructor ONLY if the class declares zero constructors of any kind. Once a class declares any custom constructor (such as a parameterized constructor), the compiler suppresses the automatic default constructor.

The Problem Scenario

class Machine {
    private String model;

    // Parameterized constructor defined: compiler does NOT generate Machine()
    public Machine(String model) {
        this.model = model;
    }
}

class Robot extends Machine {
    // Subclass constructor with no explicit super(...) call
    public Robot() {
        // The compiler attempts to insert an invisible: super();
        System.out.println("Robot initialized");
    }
}

When you compile this code, javac emits a compile-time error in Robot:

Robot.java:8: error: constructor Machine in class Machine cannot be applied to given types;
    public Robot() {
                   ^
  required: java.lang.String
  found: no arguments
  reason: actual and formal argument lists differ in length

Because Machine does not have a no-argument constructor, the compiler's attempt to insert super(); fails!

The Two Solutions

To resolve this compilation failure, you must apply one of two fixes:

  • Fix 1 (Modify Parent): Add an explicit no-argument constructor to the superclass:
    class Machine {
        public Machine() { this("Default-Model"); }
        public Machine(String model) { this.model = model; }
    }
    
  • Fix 2 (Modify Subclass): Explicitly call the available parameterized superclass constructor using super(...) as the first line of the subclass constructor:
    class Robot extends Machine {
        public Robot() {
            super("TX-900"); // Explicit super call satisfies requirement!
            System.out.println("Robot initialized");
        }
    }
    

6. Accessing Superclass Members with super

Beyond constructor chaining, the super keyword serves as a reference variable pointing to the direct superclass context of the current instance. It allows subclasses to access superclass methods or fields that have been shadowed or overridden:

public class Employee {
    public double calculatePay() {
        return 3000.0;
    }
}

public class SalesManager extends Employee {
    private double commission = 1200.0;

    @Override
    public double calculatePay() {
        // super.calculatePay() calls the superclass implementation
        return super.calculatePay() + this.commission;
    }
}

Calling new SalesManager().calculatePay() invokes super.calculatePay(), which returns 3000.0, adds 1200.0, and yields 4200.0.

Distinguishing this vs super

Keyword ExpressionPurpose / Target
this.memberRefers to an instance variable or method of the current object (checking the subclass first, then walking up the hierarchy).
super.memberExplicitly bypasses subclass overrides to access the variable or method defined in the direct superclass.
this(...)Invokes another constructor within the same class (must be statement 1).
super(...)Invokes a constructor in the direct superclass (must be statement 1).
Loading diagram...
Inheritance Hierarchy and Constructor Chaining Execution Flow
Test Your Knowledge

Given the following class declarations:

class Device {
    public Device(String model) {
        System.out.print("Device: " + model + " ");
    }
}

class SmartPhone extends Device {
    public SmartPhone() {
        System.out.print("Phone ");
    }
}
What is the result of attempting to compile and execute new SmartPhone();?

A
B
C
D
Test Your Knowledge

Which of the following statements is TRUE regarding class inheritance in the Java SE 8 programming language?

A
B
C
D
Test Your Knowledge

Consider the following subclass constructor definition:

public class Dog extends Animal {
    private String breed;

    public Dog(String name, String breed) {
        this.breed = breed;
        super(name);
    }
}
What is the result of attempting to compile this class?

A
B
C
D