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.
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
extendskeyword, Java's single inheritance constraint, the universaljava.lang.Objectclass 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
Caris-aVehicle - An
HourlyEmployeeis-aEmployee - A
CheckingAccountis-aBankAccount
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 aStringrepresentation 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 runtimeClassobject 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
publicmembers: Inherited by all subclasses regardless of package location.protectedmembers: Inherited by all subclasses in any package.- 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
privateMembers Are NOT Inherited:- A subclass does not inherit
privatefields orprivatemethods 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.
- A subclass does not inherit
- 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.
- 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(...)orthis(...), that call MUST be the very first executable statement in the constructor body. Placing any code, variable assignment, or print statement prior tosuper(...)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 }
- Mutually Exclusive: A constructor body can invoke
super(...)ORthis(...), but never both in the same constructor body, because both demand the first statement position. - Implicit
super();Insertion: If a constructor body contains neither an explicit call tosuper(...)nor a call tothis(...), the Java compiler automatically inserts an implicitsuper();(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 Expression | Purpose / Target |
|---|---|
this.member | Refers to an instance variable or method of the current object (checking the subclass first, then walking up the hierarchy). |
super.member | Explicitly 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). |
Given the following class declarations:
What is the result of attempting to compile and execute class Device {
public Device(String model) {
System.out.print("Device: " + model + " ");
}
}
class SmartPhone extends Device {
public SmartPhone() {
System.out.print("Phone ");
}
}
new SmartPhone();?
Which of the following statements is TRUE regarding class inheritance in the Java SE 8 programming language?
Consider the following subclass constructor definition:
What is the result of attempting to compile this class?public class Dog extends Animal {
private String breed;
public Dog(String name, String breed) {
this.breed = breed;
super(name);
}
}