super Keyword
The super keyword in Java gives you a direct line to the parent (superclass) from inside a child (subclass). You use it to call the parent’s constructor, access the parent’s fields, or invoke a parent method that the child has overridden — all without leaving the subclass.
Why You Need super
When a subclass inherits from a parent class, it can override fields and methods. Without super, there would be no clean way to reach the original parent version of those members. The keyword solves three problems:
- Calling the parent constructor from the child constructor.
- Accessing a parent field that the child has hidden with a field of the same name.
- Calling a parent method that the child has overridden.
Calling the Parent Constructor
Use super(...) as the first statement inside a child constructor to invoke a parent constructor. If you skip it, Java silently inserts super() (the no-arg form) — which will fail to compile if the parent has no no-arg constructor.
class Animal {
String name;
Animal(String name) {
this.name = name;
System.out.println("Animal constructor called for: " + name);
}
}
class Dog extends Animal {
String breed;
Dog(String name, String breed) {
super(name); // Must be the first statement
this.breed = breed;
System.out.println("Dog constructor called. Breed: " + breed);
}
}
public class Main {
public static void main(String[] args) {
Dog d = new Dog("Rex", "Labrador");
}
}
Output:
Animal constructor called for: Rex
Dog constructor called. Breed: Labrador
Note:
super(...)andthis(...)cannot both appear as the first statement — you can only pick one. They’re mutually exclusive at the start of a constructor.
Accessing a Parent Field
If a child class declares a field with the same name as a parent field, the child’s field shadows the parent’s. Use super.fieldName to read the parent version explicitly.
class Vehicle {
String type = "Vehicle";
}
class Car extends Vehicle {
String type = "Car"; // shadows Vehicle.type
void printTypes() {
System.out.println("Child type : " + type); // "Car"
System.out.println("Parent type : " + super.type); // "Vehicle"
}
}
public class Main {
public static void main(String[] args) {
new Car().printTypes();
}
}
Output:
Child type : Car
Parent type : Vehicle
Tip: Field shadowing is generally a design smell — prefer unique field names unless you have a very specific reason. But when you inherit code you can’t change,
super.fieldis your escape hatch.
Calling an Overridden Parent Method
This is the most common use of super. When you override a method in a subclass, you sometimes still need the parent’s logic — for example, to extend it rather than fully replace it.
class Shape {
void draw() {
System.out.println("Drawing a generic shape");
}
}
class Circle extends Shape {
@Override
void draw() {
super.draw(); // run the parent logic first
System.out.println("Drawing a circle on top of it");
}
}
public class Main {
public static void main(String[] args) {
new Circle().draw();
}
}
Output:
Drawing a generic shape
Drawing a circle on top of it
This pattern is common in GUI frameworks, logging wrappers, and template-method designs — the child extends behaviour without discarding the parent’s.
super in a Multi-Level Hierarchy
super always refers to the immediate parent, not a grandparent or higher ancestor. You cannot chain super.super.
class A {
void greet() { System.out.println("Hello from A"); }
}
class B extends A {
@Override
void greet() {
super.greet(); // calls A.greet()
System.out.println("Hello from B");
}
}
class C extends B {
@Override
void greet() {
super.greet(); // calls B.greet() (which internally calls A.greet())
System.out.println("Hello from C");
}
}
public class Main {
public static void main(String[] args) {
new C().greet();
}
}
Output:
Hello from A
Hello from B
Hello from C
Each level calls its immediate parent, creating a natural chain up the hierarchy. You get all three layers without ever doing super.super.
Quick Comparison: this vs super
| Feature | this | super |
|---|---|---|
| Refers to | Current object | Parent class portion of the object |
| Constructor call | this(...) — calls sibling constructor | super(...) — calls parent constructor |
| Field access | this.field — current class field | super.field — parent class field |
| Method call | this.method() — current class method | super.method() — parent class method |
Usable in static context? | No | No |
See this Keyword for the full picture on the other side of this pair.
Warning: Neither
supernorthiscan be used inside astaticmethod or astaticblock — they both require an active object instance.
super and Constructors — The Hidden Rule
Even when you write no explicit constructor at all, Java still ensures every parent constructor chain runs. This is possible because the compiler auto-inserts super() calls. Understanding this prevents a very common compile error.
class Parent {
Parent(int x) { // No no-arg constructor!
System.out.println("Parent: " + x);
}
}
class Child extends Parent {
Child() {
// Compiler would insert super() here — but Parent has no no-arg constructor!
// This causes: error: constructor Parent in class Parent cannot be applied
}
}
Fix: always call super(...) explicitly when the parent lacks a no-arg constructor.
class Child extends Parent {
Child() {
super(42); // explicit call — now it compiles
}
}
Under the Hood
At the bytecode level, super.method() compiles to an invokespecial instruction, while a normal virtual method call compiles to invokevirtual. The key difference:
invokevirtual— the JVM performs dynamic dispatch through the vtable, so the most-derived override runs.invokespecial— the JVM calls the method directly on the specified class, bypassing the vtable lookup entirely.
That is why super.draw() always executes Shape.draw() even if the object’s runtime type is Circle. The JVM is explicitly told “use the parent’s version.” This also applies to super(...) constructor calls — they use invokespecial to directly invoke <init> on the parent class.
This distinction matters in runtime polymorphism: you can rely on super.method() to never be re-dispatched to a deeper subclass override.
Common Mistakes
- Forgetting
super()leads to a compile error when the parent has only parameterized constructors. - Calling
superin astaticmethod — illegal;superis instance-bound. - Trying
super.super— Java does not allow skipping levels. Refactor your hierarchy if you find yourself wanting this. - Overusing
super.method()— if the child’s override is supposed to fully replace the parent’s behaviour, addingsuper.method()re-introduces code you intentionally replaced. Be deliberate.
Related Topics
- this Keyword — the companion keyword for referring to the current instance
- Method Overriding — where
super.method()is most often needed - Inheritance — the foundation that makes
supermeaningful - Constructors — understanding constructor chaining with
super() - vtable & Dynamic Dispatch — why
superusesinvokespecialinstead of a virtual call - Types of Inheritance — how multi-level hierarchies affect
superchains