Java super Keyword
Java super Keyword
The super keyword in Java is a reference to the parent class portion of the current object. It gives a child class access to three things it would otherwise be cut off from: the parent's constructor, the parent's overridden methods, and the parent's fields that are shadowed by child fields.
super only makes sense in an inheritance context — it is the counterpart to this for the parent layer. While this points to the current object, super points upward to the parent class definition within that same object. Both references exist for the same object in memory; they just give access to different layers of it.
What Is the super Keyword in Java?
The super keyword is a reference that gives a subclass explicit access to members defined in its immediate parent class. It has three distinct uses:
- ›
super()— calls a parent class constructor from within a child constructor - ›
super.method()— calls a parent class method that has been overridden in the child - ›
super.field— accesses a parent class field that is shadowed by a child field of the same name
All three uses are only valid inside non-static methods or constructors of a subclass. super cannot be used in static methods — static context has no object instance, so there is no parent layer to reference.
Three Uses of the super Keyword
| Use | Syntax | Purpose | Where Valid |
|---|---|---|---|
| Constructor call | super() or super(args) | Calls parent constructor to initialise parent fields | First statement in child constructor only |
| Method call | super.methodName() | Calls parent's overridden version of a method | Any instance method in child class |
| Field access | super.fieldName | Accesses parent field when child has a field of the same name | Any instance method or constructor in child |
Use 1 — super() — Calling the Parent Constructor
super() must be the first statement in a child constructor. It calls the parent class constructor to initialise the fields that belong to the parent. If you do not write super() explicitly, the Java compiler inserts a no-argument super() automatically — but only if the parent has a no-arg constructor. If the parent has only parameterised constructors, you must call the correct one explicitly.
1// File: Vehicle.java
2
3public class Vehicle {
4
5 private final String registrationNumber;
6 private final String brand;
7 private final int yearOfManufacture;
8
9 public Vehicle(String registrationNumber, String brand, int yearOfManufacture) {
10 this.registrationNumber = registrationNumber;
11 this.brand = brand;
12 this.yearOfManufacture = yearOfManufacture;
13 }
14
15 public String getRegistrationNumber() { return registrationNumber; }
16 public String getBrand() { return brand; }
17 public int getYearOfManufacture() { return yearOfManufacture; }
18
19 public String getBasicInfo() {
20 return brand + " (" + yearOfManufacture + ") — Reg: " + registrationNumber;
21 }
22}1// File: Truck.java
2
3public class Truck extends Vehicle {
4
5 private final double payloadCapacityTons;
6 private final int axleCount;
7
8 public Truck(String registrationNumber, String brand,
9 int yearOfManufacture, double payloadCapacityTons, int axleCount) {
10 // super() must be first — initialises Vehicle's three final fields
11 super(registrationNumber, brand, yearOfManufacture);
12 this.payloadCapacityTons = payloadCapacityTons;
13 this.axleCount = axleCount;
14 }
15
16 public double getPayloadCapacityTons() { return payloadCapacityTons; }
17 public int getAxleCount() { return axleCount; }
18
19 public String getTruckInfo() {
20 // super.getBasicInfo() accesses the parent method
21 return super.getBasicInfo()
22 + " | Payload: " + payloadCapacityTons + "T"
23 + " | Axles: " + axleCount;
24 }
25}1// File: SuperConstructorDemo.java
2
3public class SuperConstructorDemo {
4
5 public static void main(String[] args) {
6
7 Truck truck = new Truck("MH04CD5678", "Tata Prima", 2022, 35.0, 6);
8
9 System.out.println(truck.getTruckInfo());
10 System.out.println("Brand: " + truck.getBrand()); // inherited from Vehicle
11 System.out.println("Year : " + truck.getYearOfManufacture()); // inherited
12 }
13}Output:
Tata Prima (2022) — Reg: MH04CD5678 | Payload: 35.0T | Axles: 6
Brand: Tata Prima
Year : 2022
Without super(registrationNumber, brand, yearOfManufacture), the three final fields in Vehicle would never be set. registrationNumber, brand, and yearOfManufacture are private to Vehicle — the Truck constructor cannot set them directly. The only way to initialise them is through the parent constructor, which super() calls.
Use 2 — super.method() — Calling the Parent's Overridden Method
When a child class overrides a parent method, calling the method by name inside the child uses the child's version. super.method() is the only way to explicitly call the parent's version from within the child.
1// File: Account.java
2
3public class Account {
4
5 private final String accountId;
6 private double balance;
7
8 public Account(String accountId, double initialDeposit) {
9 this.accountId = accountId;
10 this.balance = Math.max(0, initialDeposit);
11 }
12
13 public String getAccountId() { return accountId; }
14 public double getBalance() { return balance; }
15
16 public boolean deposit(double amount) {
17 if (amount <= 0) return false;
18 balance += amount;
19 return true;
20 }
21
22 public boolean withdraw(double amount) {
23 if (amount <= 0 || amount > balance) return false;
24 balance -= amount;
25 return true;
26 }
27
28 public String getStatement() {
29 return "Account: " + accountId + " | Balance: Rs." + balance;
30 }
31}1// File: SavingsAccount.java
2
3public class SavingsAccount extends Account {
4
5 private final double minimumBalance;
6 private double interestRate;
7
8 public SavingsAccount(String accountId, double initialDeposit,
9 double minimumBalance, double interestRate) {
10 super(accountId, initialDeposit);
11 this.minimumBalance = minimumBalance;
12 this.interestRate = interestRate;
13 }
14
15 public double getMinimumBalance() { return minimumBalance; }
16 public double getInterestRate() { return interestRate; }
17
18 @Override
19 public boolean withdraw(double amount) {
20 // Check minimum balance rule BEFORE delegating to parent
21 double balanceAfterWithdrawal = getBalance() - amount;
22 if (balanceAfterWithdrawal < minimumBalance) {
23 System.out.println("Withdrawal rejected: balance would fall below"
24 + " minimum Rs." + minimumBalance);
25 return false;
26 }
27 // Delegate to parent's withdraw() for the actual deduction
28 return super.withdraw(amount);
29 }
30
31 public void applyMonthlyInterest() {
32 double interest = getBalance() * (interestRate / 100.0);
33 super.deposit(interest); // uses parent deposit directly — no need to override
34 System.out.println("Interest Rs." + String.format("%.2f", interest)
35 + " credited to " + getAccountId());
36 }
37
38 @Override
39 public String getStatement() {
40 // Extends parent's statement with savings-specific info
41 return super.getStatement()
42 + " | Min Balance: Rs." + minimumBalance
43 + " | Interest: " + interestRate + "%";
44 }
45}1// File: SuperMethodDemo.java
2
3public class SuperMethodDemo {
4
5 public static void main(String[] args) {
6
7 SavingsAccount savings = new SavingsAccount("SAV-001", 10000.0, 2000.0, 4.5);
8
9 System.out.println(savings.getStatement());
10
11 // Valid withdrawal — stays above minimum
12 System.out.println("\nWithdrawing Rs.5000: " + savings.withdraw(5000.0));
13 System.out.println(savings.getStatement());
14
15 // Rejected — would fall below minimum balance
16 System.out.println("\nWithdrawing Rs.4000: " + savings.withdraw(4000.0));
17
18 // Monthly interest applied
19 System.out.println();
20 savings.applyMonthlyInterest();
21 System.out.println(savings.getStatement());
22 }
23}Output:
Account: SAV-001 | Balance: Rs.10000.0 | Min Balance: Rs.2000.0 | Interest: 4.5%
Withdrawing Rs.5000: true
Account: SAV-001 | Balance: Rs.5000.0 | Min Balance: Rs.2000.0 | Interest: 4.5%
Withdrawing Rs.4000:
Withdrawal rejected: balance would fall below minimum Rs.2000.0
Interest Rs.225.00 credited to SAV-001
Account: SAV-001 | Balance: Rs.5225.0 | Min Balance: Rs.2000.0 | Interest: 4.5%
SavingsAccount.withdraw() adds a minimum balance check and then calls super.withdraw() to perform the actual deduction. Without super.withdraw(), the Truck would have to duplicate the parent's deduction logic. super.getStatement() reuses the parent's formatted string and appends savings-specific details on top. This is the "extend, don't replace" pattern that makes inheritance maintainable.
Use 3 — super.field — Accessing a Shadowed Parent Field
When a child class declares a field with the same name as a parent field, the child's field shadows the parent's — inside the child, the bare name resolves to the child's field. super.fieldName explicitly accesses the parent's version.
1// File: BaseEmployee.java
2
3public class BaseEmployee {
4
5 // Package-private — visible to subclass in same package
6 String department = "GENERAL";
7 double allowance = 5000.0;
8
9 public BaseEmployee() {}
10
11 public String getDeptInfo() {
12 return "Base Department: " + department + " | Allowance: Rs." + allowance;
13 }
14}1// File: SeniorEmployee.java
2
3public class SeniorEmployee extends BaseEmployee {
4
5 // Shadows the parent's 'department' field — same name, child version
6 String department = "SENIOR_TECH";
7 double allowance = 15000.0;
8
9 public SeniorEmployee() {
10 super(); // calls BaseEmployee()
11 }
12
13 public void showDepartments() {
14 System.out.println("Child department : " + department); // child field
15 System.out.println("Parent department : " + super.department); // parent field
16 System.out.println("Child allowance : Rs." + allowance); // child field
17 System.out.println("Parent allowance : Rs." + super.allowance); // parent field
18 }
19
20 @Override
21 public String getDeptInfo() {
22 return "Senior " + super.getDeptInfo(); // calls parent method, which uses parent field
23 }
24}1// File: SuperFieldDemo.java
2
3public class SuperFieldDemo {
4
5 public static void main(String[] args) {
6
7 SeniorEmployee senior = new SeniorEmployee();
8
9 senior.showDepartments();
10 System.out.println();
11 System.out.println(senior.getDeptInfo());
12 }
13}Output:
Child department : SENIOR_TECH
Parent department : GENERAL
Child allowance : Rs.15000.0
Parent allowance : Rs.5000.0
Senior Base Department: GENERAL | Allowance: Rs.5000.0
Field shadowing is rarely a good design choice — it confuses readers and leads to subtle bugs where the wrong field is accessed. Encapsulation through private fields avoids shadowing entirely because private fields are not visible to the child at all. The super.field use case exists to resolve accidental shadowing but is best avoided through good design.
How super Works Internally
One Object — Two Layers
super does not refer to a different object or a different memory address. The parent and child are two layers of the same object in memory.
Memory layout of new SavingsAccount(...) +--------------------------------------+ | Object header (class reference, etc.)| +--------------------------------------+ | Account fields: | <-- super refers to this layer | accountId : "SAV-001" | | balance : 10000.0 | +--------------------------------------+ | SavingsAccount fields: | <-- this refers to this layer | minimumBalance : 2000.0 | | interestRate : 4.5 | +--------------------------------------+
When you write super.withdraw(amount), the JVM does not create a new object or jump to a different memory location. It calls the Account.withdraw() method bound to the same object in memory, but uses the method resolution of the parent class rather than the child's override.
Constructor Chain with super()
new SavingsAccount("SAV-001", 10000.0, 2000.0, 4.5) called
SavingsAccount() runs first statement: super("SAV-001", 10000.0)
Account() constructor runs:
accountId = "SAV-001"
balance = 10000.0
Account() completes
SavingsAccount() body continues:
minimumBalance = 2000.0
interestRate = 4.5
SavingsAccount() completes
Object is fully initialised
Parent fields are always initialised before child fields. This ordering is guaranteed by the rule that super() must be the first statement — it ensures the parent layer of the object is valid before the child layer is set up.
super vs this — Key Differences
| Aspect | this | super |
|---|---|---|
| Refers to | Current object (current class layer) | Parent class layer of the current object |
| Field access | this.field — current class field | super.field — parent class field |
| Method call | this.method() — current class version | super.method() — parent class version (bypasses override) |
| Constructor call | this() — another constructor in the same class | super() — parent class constructor |
| Can use in static | No | No |
| Position in constructor | this() must be first statement | super() must be first statement |
| Both in one constructor | No — only one first statement allowed | No — same rule |
| When required | When parameter names shadow fields | When parent constructor must be called explicitly, or parent override must be used |
super() vs this() — Constructor Call Comparison
| Aspect | super() | this() |
|---|---|---|
| Calls | Parent class constructor | Another constructor in the same class |
| Purpose | Initialise parent fields | Constructor chaining — avoid duplication |
| Auto-inserted by compiler | Yes — if not written and parent has no-arg constructor | No — never auto-inserted |
| Required when | Parent has only parameterised constructors | You want to delegate to a sibling constructor |
| Position | First statement in child constructor | First statement in any constructor |
| Can coexist in same constructor | No | No |
When super.method() vs Calling method() Directly
| Scenario | Use | Reason |
|---|---|---|
| Child has overridden the method and wants its own behaviour | method() | Calls the child's own override — normal polymorphism |
| Child wants to invoke parent behaviour while extending it | super.method() | Runs parent logic, then child adds to it |
| Child wants to completely replace parent behaviour | method() with full new body | Override without calling super |
| Checking whether the call goes to parent or child | super.method() for parent, method() for child | Explicit disambiguation |
Real-World Example — Logistics Vehicle Hierarchy
The Business Problem
You are building the vehicle management system for a logistics company — similar to what Delhivery or Ecom Express uses for its fleet operations. The system has a base LogisticsVehicle with common registration and capacity data, a DeliveryVan subclass for last-mile delivery, and an AirCargo subclass for long-distance freight. All three levels use super() to chain constructor initialisation, super.method() to extend reporting behaviour, and polymorphism through a shared base type.
Implementation
1// File: LogisticsVehicle.java
2
3public class LogisticsVehicle {
4
5 private final String vehicleId;
6 private final String operatorName;
7 private final double maxCargoKg;
8 private double currentCargoKg;
9
10 public LogisticsVehicle(String vehicleId, String operatorName, double maxCargoKg) {
11 if (maxCargoKg <= 0) throw new IllegalArgumentException("Max cargo must be positive.");
12 this.vehicleId = vehicleId;
13 this.operatorName = operatorName;
14 this.maxCargoKg = maxCargoKg;
15 this.currentCargoKg = 0.0;
16 }
17
18 public String getVehicleId() { return vehicleId; }
19 public String getOperatorName() { return operatorName; }
20 public double getMaxCargoKg() { return maxCargoKg; }
21 public double getCurrentCargoKg() { return currentCargoKg; }
22 public double getAvailableKg() { return maxCargoKg - currentCargoKg; }
23
24 public boolean loadCargo(double weightKg) {
25 if (weightKg <= 0 || weightKg > getAvailableKg()) return false;
26 currentCargoKg += weightKg;
27 return true;
28 }
29
30 public void unloadAll() {
31 currentCargoKg = 0.0;
32 }
33
34 public String getReport() {
35 return vehicleId + " | Operator: " + operatorName
36 + " | Load: " + currentCargoKg + "/" + maxCargoKg + " kg";
37 }
38}1// File: DeliveryVan.java
2
3public class DeliveryVan extends LogisticsVehicle {
4
5 private final String zone;
6 private int deliveriesCompleted;
7 private static final int MAX_DELIVERIES_PER_DAY = 30;
8
9 public DeliveryVan(String vehicleId, String operatorName,
10 double maxCargoKg, String zone) {
11 super(vehicleId, operatorName, maxCargoKg); // initialises LogisticsVehicle fields
12 this.zone = zone;
13 this.deliveriesCompleted = 0;
14 }
15
16 public String getZone() { return zone; }
17 public int getDeliveriesCompleted() { return deliveriesCompleted; }
18
19 public boolean makeDelivery(double packageWeightKg) {
20 if (deliveriesCompleted >= MAX_DELIVERIES_PER_DAY) {
21 System.out.println(getVehicleId() + ": Daily delivery limit reached.");
22 return false;
23 }
24 // super.loadCargo check not needed — package unloaded on delivery
25 if (packageWeightKg > getCurrentCargoKg()) {
26 System.out.println(getVehicleId() + ": Package heavier than current load.");
27 return false;
28 }
29 deliveriesCompleted++;
30 return true;
31 }
32
33 @Override
34 public String getReport() {
35 // Extends parent report with van-specific delivery data
36 return super.getReport()
37 + " | Zone: " + zone
38 + " | Deliveries today: " + deliveriesCompleted;
39 }
40}1// File: AirCargo.java
2
3public class AirCargo extends LogisticsVehicle {
4
5 private final String flightNumber;
6 private final String destinationCity;
7 private final boolean isTemperatureControlled;
8
9 public AirCargo(String vehicleId, String operatorName,
10 double maxCargoKg, String flightNumber,
11 String destinationCity, boolean isTemperatureControlled) {
12 super(vehicleId, operatorName, maxCargoKg); // initialises LogisticsVehicle fields
13 this.flightNumber = flightNumber;
14 this.destinationCity = destinationCity;
15 this.isTemperatureControlled = isTemperatureControlled;
16 }
17
18 public String getFlightNumber() { return flightNumber; }
19 public String getDestinationCity() { return destinationCity; }
20 public boolean isTemperatureControlled() { return isTemperatureControlled; }
21
22 @Override
23 public boolean loadCargo(double weightKg) {
24 // Air cargo has stricter weight checks — validate before parent logic
25 if (weightKg > 500.0) {
26 System.out.println(getVehicleId() + ": Single consignment limit is 500 kg.");
27 return false;
28 }
29 return super.loadCargo(weightKg); // delegate to parent for actual loading
30 }
31
32 @Override
33 public String getReport() {
34 return super.getReport()
35 + " | Flight: " + flightNumber
36 + " | To: " + destinationCity
37 + " | Temp-controlled: " + isTemperatureControlled;
38 }
39}1// File: LogisticsDemo.java
2
3import java.util.List;
4
5public class LogisticsDemo {
6
7 public static void main(String[] args) {
8
9 DeliveryVan van = new DeliveryVan(
10 "VAN-MUM-001", "Rajesh Kumar", 800.0, "South Mumbai"
11 );
12
13 AirCargo air = new AirCargo(
14 "AC-DEL-007", "SpiceJet Cargo", 10000.0,
15 "SG-457", "Delhi", true
16 );
17
18 // Load cargo on both vehicles
19 van.loadCargo(350.0);
20 air.loadCargo(400.0);
21 air.loadCargo(600.0); // rejected — single consignment > 500 kg
22 air.loadCargo(300.0);
23
24 System.out.println("=== Fleet Report ===\n");
25
26 // Polymorphic report — both called via LogisticsVehicle reference
27 List<LogisticsVehicle> fleet = List.of(van, air);
28 for (LogisticsVehicle vehicle : fleet) {
29 System.out.println(vehicle.getReport()); // calls overridden version
30 }
31
32 System.out.println("\nVan makes a delivery:");
33 van.makeDelivery(50.0);
34 System.out.println(van.getReport());
35 }
36}Output:
AC-DEL-007: Single consignment limit is 500 kg.
=== Fleet Report ===
VAN-MUM-001 | Operator: Rajesh Kumar | Load: 350.0/800.0 kg | Zone: South Mumbai | Deliveries today: 0
AC-DEL-007 | Operator: SpiceJet Cargo | Load: 700.0/10000.0 kg | Flight: SG-457 | To: Delhi | Temp-controlled: true
Van makes a delivery:
VAN-MUM-001 | Operator: Rajesh Kumar | Load: 350.0/800.0 kg | Zone: South Mumbai | Deliveries today: 1
Every constructor calls super() to initialise LogisticsVehicle. AirCargo.loadCargo() adds a per-consignment check then calls super.loadCargo() to do the actual load. Both subclasses call super.getReport() to include the base report and append their own fields — the string builds up through the chain. The polymorphic loop calls vehicle.getReport() on a LogisticsVehicle reference and gets the full subclass-specific output.
Best Practices
Always call super() explicitly when the parent has no no-arg constructor
Relying on the compiler to insert super() only works when the parent has a no-argument constructor. When the parent requires arguments — which is most well-designed classes — you must write super(args) explicitly. An explicit super() call is always clearer than relying on implicit insertion, even when the no-arg version exists.
Use super.method() to extend — not replace — parent behaviour
The most valuable pattern is using super.method() when a child wants to add to the parent's behaviour rather than completely replace it. Override getReport() in the child, call super.getReport() to get the parent string, then append child-specific details. This creates a chain where each layer adds its contribution — similar to decorator stacking.
Do not skip parent methods without a clear reason
When a child overrides a method but does not call super.method(), it completely replaces the parent's logic. This is appropriate when the child genuinely needs different behaviour. It is a bug when the parent's logic was needed and simply forgotten. During code reviews, overrides that do not call super are examined to confirm the omission is intentional.
Never access parent fields directly through super.field — use parent methods
super.field accesses parent fields that are not private. This breaks the parent class's encapsulation — the child reaches into parent internal state. Access parent state through the parent's public or protected methods instead. Well-encapsulated parent classes make super.field unnecessary.
Common Mistakes
Mistake 1 — super() Not the First Statement
1public class SavingsAccount extends Account {
2
3 private double interestRate;
4
5 public SavingsAccount(String accountId, double deposit, double rate) {
6 this.interestRate = rate; // compile error — super() must come first
7 super(accountId, deposit); // error: call to super must be first statement
8 }
9}Compile error: call to super must be first statement in constructor
Any statement before super() is a compile-time error. Java enforces this because parent fields must be initialised before child fields — you cannot set up the child layer before the parent layer exists.
Mistake 2 — Using super in a Static Method
1public class Child extends Parent {
2
3 public static void staticMethod() {
4 // super.someMethod(); // compile error — super not valid in static context
5 System.out.println("No super available in static methods");
6 }
7}Static methods belong to the class, not to any object instance. super requires a specific object instance to reference the parent layer of — it is meaningless in a static context. The compiler rejects any use of super inside a static method.
Mistake 3 — Forgetting super() When Parent Has No No-Arg Constructor
1public class Shipment {
2 private final String trackingId;
3
4 // Only a parameterised constructor — no no-arg version
5 public Shipment(String trackingId) {
6 this.trackingId = trackingId;
7 }
8}
9
10public class PriorityShipment extends Shipment {
11
12 private String priorityLevel;
13
14 public PriorityShipment(String trackingId, String priorityLevel) {
15 // Missing super(trackingId) — compiler tries to insert super()
16 // but Shipment has no no-arg constructor
17 // Compile error: constructor Shipment in class Shipment
18 // cannot be applied to given types: required String, found no arguments
19 this.priorityLevel = priorityLevel;
20 }
21}Compile error: constructor Shipment in class Shipment cannot be applied to given types
The fix is to add super(trackingId) as the first statement in PriorityShipment. The compiler's auto-insertion of super() only works when the parent has a no-argument constructor.
Mistake 4 — Calling super() from a Non-Constructor
1public class Child extends Parent {
2
3 public void someMethod() {
4 super(); // compile error — super() can only be called from a constructor
5 }
6}super() — the constructor call form — can only appear inside a constructor body, as its first statement. To call a parent method from a non-constructor, use super.methodName(). The two forms are syntactically similar but completely different: super() is a constructor call; super.method() is a regular method call.
Interview Questions
Q1. What are the uses of the super keyword in Java?
super has three uses. super() or super(args) calls the parent class constructor — it must be the first statement in a child constructor and is required when the parent has no no-arg constructor. super.method() calls the parent's version of an overridden method — used when the child wants to extend rather than completely replace the parent's behaviour. super.field accesses a parent field that is shadowed by a child field of the same name — rare in practice since encapsulation through private fields avoids the need for it.
Q2. What is the difference between super and this in Java?
this refers to the current object — it gives access to the current class's own fields, methods, and constructors. super refers to the parent class layer of the current object — it gives access to the parent's fields, methods, and constructor. Both refer to the same object in memory, just to different layers of it. Both are unavailable in static methods. In a constructor, either this() or super() can be the first statement — never both.
Q3. What happens if you do not call super() in a child constructor?
The Java compiler automatically inserts super() — a call to the parent's no-argument constructor — as the first statement. This is transparent if the parent has a no-arg constructor. If the parent has only parameterised constructors and no no-arg constructor, the auto-insertion fails and the compiler reports an error: the child must explicitly call the appropriate parent constructor with super(args). This error is extremely common when extending classes that follow the "always require parameters at construction" design.
Q4. Can super() and this() both appear in the same constructor?
No. Both super() and this() must be the first statement in a constructor, and there can be only one first statement. Java enforces that exactly one of them — or neither — appears at the start. If a constructor chains to a sibling with this(), that sibling is responsible for the super() call. If a constructor calls super() directly, it cannot also call this().
Q5. Why would you call super.method() inside an overriding child method?
When the child wants to reuse the parent's implementation and add to it rather than replace it entirely. This is the "extend, don't replace" pattern. A child getReport() calls super.getReport() to get the parent's formatted string, then appends its own additional details. A child withdraw() validates an extra condition and then calls super.withdraw() to perform the actual deduction. Without super.method(), the child must duplicate the parent's logic or lose it entirely — both are worse outcomes.
Q6. What is the difference between method overriding and calling super.method()?
Method overriding is when a child declares a method with the same signature as a parent method — the child's version replaces the parent's in the method dispatch chain. super.method() is how the child's overriding method explicitly invokes the parent's version from within its own body. They are complementary: overriding changes which method is called by default through polymorphism; super.method() gives the override the ability to delegate upward selectively.
FAQs
What does super mean in Java?
super is a reference to the parent class portion of the current object. It allows a child class to call its parent's constructor (super()), invoke the parent's version of an overridden method (super.method()), or access a parent field that the child has shadowed (super.field).
Is super() mandatory in every child constructor?
Not syntactically — the compiler inserts super() automatically if you omit it, but only if the parent has a no-arg constructor. It is mandatory only when the parent requires constructor arguments. Many teams write super() explicitly in every child constructor as a best practice for clarity, even when the compiler would insert it.
Can you use super in a static method?
No. super requires a specific object instance — it refers to the parent layer of that instance. Static methods belong to the class and have no instance, so super is meaningless and the compiler rejects it.
What is the difference between super.method() and method() in a child class?
method() inside a child class calls the child's own version — the overriding implementation. super.method() bypasses the override and calls the parent's version directly. The difference only exists when the method is overridden in the child. If the method is not overridden, both resolve to the parent's implementation.
Can super access private members of the parent class?
No. private members are invisible to subclasses — super.privateField and super.privateMethod() are compile-time errors. Private fields must be accessed through the parent's public or protected methods. This is why encapsulation through private fields is preferred — it ensures the parent's internal state is always accessed through controlled methods.
How many levels up can super go?
Only one level — to the immediate parent. super.super.method() is not valid Java. If C extends B extends A and C needs to call A's version of a method that B overrides, it cannot do so directly through super. The usual solution is to redesign the hierarchy so B exposes a way to invoke A's logic, or to use a different structure altogether.
Summary
super gives a child class controlled access to its parent layer — the constructor it inherits from, the methods it overrides, and the fields it shadows. Of the three uses, super() in constructors and super.method() in overrides are the ones that appear daily in production code. super.field is a design smell best avoided through encapsulation.
The constructor chain rule — super() must be the first statement — is not arbitrary. It guarantees the parent layer is fully initialised before the child layer is built on top of it. The method call use — super.method() inside an override — is what makes the "extend, don't replace" pattern possible, letting each class in the hierarchy contribute its layer to the result.
For interviews, be ready to explain all three uses of super by name, demonstrate the difference between super and this with the "same object, different layers" mental model, and show why super() must be the first statement in a child constructor. These points appear in both service-based recall questions and product-based design discussions about inheritance hierarchies.
What to Read Next
| Topic | Link |
|---|---|
| How the this keyword references the current object layer within instance methods | Java this Keyword → |
| How inheritance uses super() and super.method() across class hierarchies | Java Inheritance → |
| How constructors use super() to chain parent initialisation | Java Constructors → |
| How polymorphism uses method overriding that super.method() bypasses | Java Polymorphism → |
| How abstract classes define parent behaviour that subclasses extend with super | Java Abstract Classes → |