Guidelines for Initializing Parent Class Instances in Java Subclasses
When a Java subclass is instentiated, the JVM automatically triggers parent class constructor execution first to initialize all fields defined in the parent type. If a subclass does not explicitly specify a parent constructor to call, the compiler will implicitly insert a call to the parent class's no-argument constructor as the first line of the subclass constructor. If the parent class does not expose an accessible no-argument constructor (i.e., only parameterized constructors are defined), the subcclass must explicitly call one of the parent's parameterized constructors to pass required initialization values, otherwise a compilation error will occur.
Explicit Parent Constructor Invocation
You can use the super() statement as the first line of a subclass constructor to explicitly invoke a specified parent class constructor, passsing required initialization parameters to the parent. The following example demonstrates this implementation:
class BaseProduct {
private int productId;
public BaseProduct(int productId) {
this.productId = productId;
}
public void printProductId() {
System.out.println("Product ID: " + productId);
}
}
class DigitalProduct extends BaseProduct {
private String productBrand;
public DigitalProduct(int id, String brand) {
super(id);
this.productBrand = brand;
}
public void printBrand() {
System.out.println("Product Brand: " + productBrand);
}
}
public class InitializationDemo {
public static void main(String[] args) {
DigitalProduct laptop = new DigitalProduct(247, "Lenovo");
laptop.printProductId();
laptop.printBrand();
}
}
In this example, DigitalProduct inherits from BaseProduct, which only has a parameterized constructor that accepts a product ID. The subclass constructor calls super(id) to pass the input ID value to the parent constructor for field initialization before initializing its own productBrand field.
Selecting Different Parent Constructor Overloads
The super() statement supports passing variable parameters, so you can match different parent constructor overloads by adjusting the number, type, and order of parameters passed to super(), adapting to different subclass initialization scenarios. The following example shows how to call the same parent constructor with different default values based on subclass constructor inputs:
class BaseProduct {
private int productId;
public BaseProduct(int productId) {
this.productId = productId;
}
public void printProductId() {
System.out.println("Product ID: " + productId);
}
}
class DigitalProduct extends BaseProduct {
private String productBrand;
// Two-parameter constructor for full initialization
public DigitalProduct(int id, String brand) {
super(id);
this.productBrand = brand;
}
// Single-parameter constructor with default product ID
public DigitalProduct(String brand) {
super(0);
this.productBrand = brand;
}
public void printBrand() {
System.out.println("Product Brand: " + productBrand);
}
}
public class MultiConstructorDemo {
public static void main(String[] args) {
DigitalProduct laptop = new DigitalProduct(247, "Lenovo");
laptop.printProductId();
laptop.printBrand();
DigitalProduct accessory = new DigitalProduct("Anker");
accessory.printProductId();
accessory.printBrand();
}
}
This implementation includes two overloaded constructors for the DigitalProduct subclass. The two-parameter constructor passes a user-provided ID to the parent, while the single-parameter constructor passes a default ID of 0 to the parent for scenarios where a product ID is not specified during instantiation.