Implementing class inheritance in Java establishes hierarchical type relationships, directly improving code reuse, system extensibility, and long-term maintainability. When a subclass extends a superclass, it acquires all non-private fields and methods. Private members remain encapsulated within the parent class and require public or protected accessor methods for indirect interaction.
Constructor execution follows a strict chaining mechanism. Instantiating a subclass automatically triggers the parent class constructor to ensure proper state initialization. By default, the compiler inserts an implicit call to the superclass no-argument constructor. If the parent lacks a no-arg constructor, the subclass must explicitly invoke super(arguments) as the very first statement in its constructor. Because both super() and this() mandate placement on the first line, they cannot coexist within the same constructor block. This initialization cascade continues recursively up the hierarchy until java.lang.Object is reached, which serves as the universal base for all Java classes.
Java enforces a single-inheritance model for classes, meaning a type can directly extend only one parenet. Multi-level hierarchies are fully supported, but multiple direct inheritance is prohibited. Design decisions should strictly adhere to the "is-a" relationship principle. Extending a class solely for code reuse without a logical subtype relationship violates object-oriented design norms and leads to fragile architectures.
Field resolution during runtime operates on a bottom-up traversal strategy. When a property is accessed on an instance, the JVM first inspects the object's immediate class definition. If the field exists and is accessible, its value is returned. If absent, the search moves to the direct superclass, repeating the process until the member is located or the Object class boundary is reached. This lookup behavior directly mirrors the memory layout of inherited objects, where parent state is allocated contiguously with child state on the heap.
public class FieldResolutionDemo {
public static void main(String[] args) {
SportsCar vehicle = new SportsCar();
// Member lookup sequence:
// 1. Inspect the current class for the requested field.
// 2. Return the value if the field exists and visibility permits access.
// 3. If missing, traverse to the immediate superclass.
// 4. Repeat upward through the hierarchy until the field is resolved.
System.out.println(vehicle.model); // Resolves to: Cyberster
System.out.println(vehicle.productionYear); // Resolves to: 2024
System.out.println(vehicle.powerSource); // Resolves to: Battery Pack
}
}
class Machine {
String model = "Industrial Unit";
String powerSource = "Grid";
}
class Automobile extends Machine {
String model = "Standard Sedan";
int productionYear = 2024;
// private int productionYear = 2024;
// Private fields require getter methods for subclass visibility
}
class SportsCar extends Automobile {
String model = "Cyberster";
// productionYear is inherited from Automobile
// powerSource is inherited from Machine
}