backend

9 min read

Super Keyword in Java Explained

Stop guessing when to use super() in Java. This guide shows you exactly how the super keyword works with constructors, methods, and fields - with real code you can copy.

Super Keyword in Java Explained thumbnail

Published By: Nelson Djalo | Date: April 8, 2026

If you have ever written extends in Java and then wondered how a child class actually talks to its parent, the super keyword is the answer. It is the shortcut Java gives you to reach "up" into the class you inherited from - whether that is calling the parent constructor, running a parent method, or grabbing a parent field that got shadowed.

Most bugs around super come from not knowing the three places you can use it and the one place you cannot. By the end of this post you will know exactly when to type super, when Java adds it for you, and why your compiler sometimes screams at you about it.

Table of Contents

What 'super' Actually Means in Java

super is a reference to the immediate parent class of the current object. When you write class Car extends Vehicle, inside Car the keyword super points to the Vehicle part of that Car instance. It is not a separate object - every Car is a Vehicle, and super is how you access that inherited half.

Think of it like this. Your Car object has two layers - the Vehicle fields and methods it inherited, plus its own new stuff. this refers to the whole object. super refers only to the inherited layer. That mental model will save you an hour of debugging the first time you hit a field shadowing issue.

If you are new to inheritance in general, start with Java for Beginners before going deeper on this.

The 3 Main Uses of super

There are exactly three things super does. Learn these and you have covered 99% of real-world code.

1. Calling the Parent Constructor with super()

When a child class is constructed, the parent constructor must run first. You call it with super(...) and it must be the first statement in your constructor.

class Vehicle {
    protected String brand;
    protected int wheels;

    public Vehicle(String brand, int wheels) {
        this.brand = brand;
        this.wheels = wheels;
    }
}

class Car extends Vehicle {
    private int doors;

    public Car(String brand, int doors) {
        super(brand, 4); // must be first line
        this.doors = doors;
    }
}

If Vehicle had no constructor that accepted those arguments, this would not compile. That is the compiler protecting you - it refuses to build a Car without first building a valid Vehicle.

2. Accessing Parent Methods with super.methodName()

When a child class overrides a method, super.methodName() lets you call the original parent version. This is the pattern for extending behavior instead of replacing it.

class Vehicle {
    public String describe() {
        return "A " + wheels + "-wheel " + brand;
    }
}

class Car extends Vehicle {
    private int doors;

    @Override
    public String describe() {
        return super.describe() + " with " + doors + " doors";
    }
}

Calling new Car("Toyota", 4).describe() returns "A 4-wheel Toyota with 4 doors". You reused the parent's logic instead of rewriting it.

3. Accessing Parent Fields with super.fieldName

If a child class declares a field with the same name as a parent field, the child's version shadows the parent's. super.fieldName gets you back to the parent's copy.

class Vehicle {
    protected String type = "generic vehicle";
}

class Car extends Vehicle {
    protected String type = "passenger car";

    public void printTypes() {
        System.out.println("Child type: " + this.type);
        System.out.println("Parent type: " + super.type);
    }
}

Output:

Child type: passenger car
Parent type: generic vehicle

Field shadowing is almost always a smell - prefer renaming the field. But when you inherit a legacy class you cannot change, super.field is how you escape the shadow.

When super() Is Implicit vs Explicit

If you do not write super() yourself, Java inserts a no-argument super() call as the first line of every constructor. This is why code like this just works:

class Vehicle {
    public Vehicle() {
        System.out.println("Vehicle built");
    }
}

class Car extends Vehicle {
    public Car() {
        System.out.println("Car built");
    }
}

new Car() prints both lines because the compiler secretly added super() to Car's constructor. The moment the parent does not have a no-arg constructor, you must call super(...) explicitly or the code will not compile. That is the most common "why won't this compile" moment for students learning inheritance.

super vs this - The Quick Comparison

These two keywords get confused a lot. Here is the difference in one table.

KeywordRefers toUse it for
thisCurrent objectOwn fields, own methods, chaining to another constructor via this(...)
superParent class part of current objectParent fields, parent methods, parent constructor via super(...)

One important rule - you can use this(...) or super(...) in a constructor but not both, and whichever you use must be the first line. For a deeper dive on the other side of this, read The 'this' Keyword in Java.

Method Overriding Scenarios

The classic use case for super is the "extend, do not replace" pattern. Imagine a logging method on a base class that every subclass should still run.

class Vehicle {
    public void start() {
        System.out.println("Running safety checks");
    }
}

class Car extends Vehicle {
    @Override
    public void start() {
        super.start(); // keep the safety checks
        System.out.println("Starting engine");
    }
}

If you forget super.start() in the child, the safety check never runs and you ship a bug. This is why Spring and other frameworks document when subclasses "must call super" in their Javadocs.

Field Shadowing - A Tricky Example

Field access in Java is not polymorphic the way method calls are. This trips up even experienced devs.

class Vehicle {
    String label = "vehicle";
}

class Car extends Vehicle {
    String label = "car";
}

Vehicle v = new Car();
System.out.println(v.label); // prints "vehicle"

Why? Because the compiler looks at the declared type (Vehicle) not the runtime type (Car) when resolving fields. Method calls resolve at runtime, field access resolves at compile time. If you want the child's label, cast to Car or use a getter method. If you want to avoid this whole mess, do not shadow fields in the first place.

Multi-Level Inheritance with super

super only reaches up one level. There is no super.super.method() in Java. If you have GrandParent -> Parent -> Child, the Child can only call super.method() which goes to Parent. To hit GrandParent, Parent must expose it.

class Vehicle {
    public String id() { return "vehicle"; }
}

class Car extends Vehicle {
    @Override
    public String id() { return "car"; }
}

class SportsCar extends Car {
    @Override
    public String id() {
        return super.id() + " -> sports"; // goes to Car, not Vehicle
    }
}

Calling new SportsCar().id() returns "car -> sports". If you want Vehicle's version, you would need a method on Car like parentId() that returns super.id(), and then SportsCar would call parentId(). This limitation is deliberate - deep inheritance chains that need to skip levels are usually a design smell. If you find yourself fighting this, consider composition or check out Abstract Class vs Interface for alternatives.

Common Mistakes to Avoid

A few places where super will bite you if you are not careful.

Using super in a Static Context

super refers to the parent part of an instance. Static methods have no instance, so super is illegal inside them.

class Car extends Vehicle {
    public static void info() {
        super.describe(); // compile error
    }
}

If you need to call a parent static method, just call it by the parent class name like Vehicle.staticMethod().

super Inside Interfaces

Interfaces do not have a single parent class, so plain super does not work inside default methods. Java 8 introduced a special syntax for calling a specific interface's default method - InterfaceName.super.method().

interface Logger {
    default void log() { System.out.println("log"); }
}

interface Auditor {
    default void log() { System.out.println("audit"); }
}

class Service implements Logger, Auditor {
    @Override
    public void log() {
        Logger.super.log();
        Auditor.super.log();
    }
}

This is the only time you qualify super with a type name, and it only exists because a class can implement multiple interfaces with clashing default methods.

Calling super() After Other Code

The call to super(...) must be the first statement in the constructor. You cannot run validation, log something, or call another helper before it.

public Car(String brand) {
    System.out.println("Building car"); // compile error
    super(brand, 4);
}

Java 22 added a preview feature allowing statements before super(...) in limited cases, but in every mainstream codebase today, treat "super first" as the rule.

FAQ

Do I always need to call super() in a constructor?

No. If the parent has a no-arg constructor, Java calls super() for you automatically. You only need to write it explicitly when the parent requires arguments or when you want to be clear about what is happening.

Can I use super to skip to a grandparent class?

No. super always refers to the immediate parent. If you need the grandparent's behavior, the parent class has to expose it through its own method.

What happens if I forget to call super.method() when overriding?

Nothing - the parent version simply does not run. This can be a bug or a feature depending on what you want. Read the Javadoc of the method you are overriding to see if the parent author expected you to call super.

Is super the same as this?

No. this refers to the whole current object. super refers only to the parent class portion of it. You use super when the child has shadowed a field or overridden a method and you still need the original.

Can I use super in a static method?

No. Static methods belong to the class, not an instance, so there is no "parent part of this object" to reference. Call the parent's static method by its class name instead.

Wrapping Up

super is a small keyword with three clear jobs - call the parent constructor, call an overridden parent method, and read a shadowed parent field. Get those three patterns into your muscle memory and inheritance stops being scary.

Want to go from "I know what super does" to "I can design a real class hierarchy"? The Java Master Class walks you through inheritance, polymorphism, and the rest of OOP with projects you can put on your resume.

Your Career Transformation Starts Now

Join thousands of developers mastering in-demand skills with Amigoscode. Try it free today.