Java Super Keyword

The super keyword provides a way to access members and methods of the superclass from within the subclass, allowing you to create and manage inheritance relationships effectively. The super keyword plays a crucial role in object-oriented programming, where classes are organized in a hierarchy to promote code reuse and specialization.

Super keyword

The super keyword is used to refer to the superclass (parent class) of a subclass (child class). It allows you to access or invoke members (variables, methods, and constructors) of the superclass from within the subclass. The super keyword is essential for maintaining the inheritance hierarchy, overriding methods, and managing the relationship between classes. It helps in avoiding naming conflicts, extending behaviour, and promoting code reuse.

Characteristics of super Keyword:

Constructors Invocation: When creating a subclass, its constructor must invoke the constructor of its parent class using “super()”. This ensures proper initialization of the superclass’s state.

Method Invocation: A subclass can use “super” to call a method defined in its parent class. This is helpful when the subclass desires to include the parent class’s method implementation along with its own.

Field Access: Access to a parent class’s field is feasible via “super”. This enables the subclass to access the parent class’s version of a field.

Constructor Order: In a constructor of the subclass, the “super()” statement must be the foremost one when invoking a superclass constructor.

Static Context Limitation: The use of “super” is disallowed within a static context, like a static method or a static variable initializer.

Optional for Method Invocation: While “super” can be employed to call a parent class method, it is not obligatory. When a method is not overridden in the subclass, invoking it without “super” will engage the parent class’s implementation.

Key advantages of using the super keyword:

Method Overriding: The super keyword enables precise control over method overriding. It allows a subclass to invoke the overridden method of the superclass, facilitating the extension of behaviour while preserving the original functionality.

Avoiding Naming Conflicts: When a subclass and superclass have members (variables or methods) with the same name, the super keyword allows you to explicitly refer to the superclass version, avoiding ambiguity and ensuring proper access to intended members.

Initialization Sequence: In the constructor chaining process, the super keyword allows the subclass constructor to invoke a specific constructor of the superclass, ensuring proper initialization of superclass-specific properties before subclass properties are initialized.

Accessing Superclass Resources: By using the super keyword, you can access and leverage resources (variables, methods, or constructors) of the superclass, promoting code reuse and reducing redundancy.

Managing Inheritance Hierarchies: The super keyword maintains the relationship between subclasses and superclasses, contributing to the coherent organization of class hierarchies and enhancing code clarity.

Explicit Invocation: The super keyword provides explicitness when invoking superclass members, making code more self-explanatory and reducing the chance of unintended behaviour.

Polymorphism and Dynamic Dispatch: In polymorphic scenarios, the super keyword contributes to dynamic method dispatch, allowing the appropriate version of a method to be executed based on the runtime object type.

Enforcing Design Patterns: The super keyword supports design patterns such as the Template Method and Factory Method, where subclasses need to interact with or override specific parts of the superclass behaviour.

Code Maintenance and Readability: Proper use of the super keyword enhances the maintainability and readability of code by providing clear indications of superclass interactions and intentions.

1. Accessing Superclass Members:

This is especially useful when a subclass has members with the same name as those in the superclass. By using super, you can explicitly refer to the superclass version of the member.

Accessing Superclass Members

Example Program:

class Vehicle {
    String type = "Generic Vehicle";
    void displayType() {
        System.out.println("Type: " + type);
    }
}
class Car extends Vehicle {
    String type = "Car";
    void displayType() {
        System.out.println("Subclass Type: " + type);         // Accessing subclass variable
        System.out.println("Superclass Type: " + super.type); // Accessing superclass variable
    }
    void showTypes() {
        displayType();  // Calls the overridden method in Car class
        super.displayType();  // Calls the method from the superclass
    }
}
class  TechVidvan{
    public static void main(String[] args) {
        Car car = new Car();
        car.displayType();
        System.out.println("\nUsing showTypes:");
        car.showTypes();
    }
}

Output:

Subclass Type: Car
Superclass Type: Generic Vehicle

Using show types:
Subclass Type: Car
Superclass Type: Generic Vehicle
Type: Generic Vehicle

Explanation:

This code defines a Vehicle class with a type and a method to display it, and a Car subclass that overrides the method to differentiate between the subclass and superclass types.

The main method demonstrates accessing and displaying these types using the super keyword.

2. Method Overriding with super keyword:

In an overridden method of the subclass, you can use the super keyword to call the superclass version of the method. This allows you to extend the behaviour of the superclass method while still utilizing its original implementation.

Method Overriding with super keyword

Example Program:

class Parent {
    String message = "Hello from Parent";
    void display() {
        System.out.println(message);
    }
}
class Child extends Parent {
    String message = "Hello from Child";
    void display() {
        super.display();  // Invoking the parent class method
        System.out.println(message);
    }
}
class TechVidvan{
    public static void main(String[] args) {
        Child child = new Child();
        child.display();
    }
}

Output:

Hello from Parent
Hello from Child

Explanation:

The Parent class has a member variable message and a method display that prints the message.The Child class extends the Parent and overrides the display method.

It uses the super.display() call to invoke the display method from the parent class before adding its own message.In the TechVidvan class, an object of the Child class is created, and its display method is called.

3. Accessing super class Attributes:

class Animal {
    String name;
    Animal(String name) {
        this.name = name;
    }
    void makeSound() {
        System.out.println(name + " makes a sound");
    }
}
class Dog extends Animal {
    String name;
    Dog(String name) {
        super(name);  // Invoking superclass constructor
        this.name = "Dog: " + name;
    }
    @Override
    void makeSound() {
        super.makeSound();  // Call superclass method
        System.out.println(name + " barks");
    }
}
class TechVidvan{
    public static void main(String[] args) {
        Dog dog = new Dog("Buddy");
        dog.makeSound();
    }
}

Output:

Buddy makes a sound
Dog: Buddy barks

Explanation:

The Animal class has a member variable name, a constructor to set the name, and a method makeSound to display the sound of the animal. The Dog class extends Animal and overrides the makeSound method.

It also defines its own version of the name variable and constructor that utilizes the super keyword to call the superclass constructor.

In the TechVidvan class, an object of the Dog class is created with the name “Buddy,” and the makeSound method is called.

4. Invoking Superclass No-argument Constructor:

When creating an object of a subclass, the constructor of the superclass is implicitly called. You can use the super keyword to invoke a specific constructor of the superclass, particularly if the superclass constructor requires arguments.

Example Code:

class Animal {
    String species;
    Animal() {
        species = "Unknown";
        System.out.println("Animal no-arg constructor invoked");
    }
    void display() {
        System.out.println("Species: " + species);
    }
}
class Dog extends Animal {
    String breed;
    Dog(String breed) {
        super(); // Calling the no-arg constructor of the superclass
        this.breed = breed;
        System.out.println("Dog constructor invoked");
    }
    void displayBreed() {
        System.out.println("Breed: " + breed);
    }
}
class TechVidvan{
    public static void main(String[] args) {
        Dog dog = new Dog("Golden Retriever");
        dog.display();
        dog.displayBreed();
    }
}

Output:

Animal no-arg constructor invoked
Dog constructor invoked
Species: Unknown
Breed: Golden Retriever

Explanation:

The Animal class has a no-argument constructor that initializes the species to “Unknown” and prints a message when the constructor is invoked.

The Dog class extends Animal and has its own constructor that takes a breed parameter. It uses the super() call to invoke the no-argument constructor of the Animal superclass.

The display method in the Animal class prints the species, and the displayBreed method in the Dog class prints the breed.

In the TechVidvan class, an object of the Dog class is created with the breed “Golden Retriever,” and then the display and displayBreed methods are called.

5. Invoking Superclass Parametarized Constructor:

class Person {
    String name;
    Person(String name) {
        this.name = name;
        System.out.println("Person constructor invoked");
    }
}
class Student extends Person {
    int rollNumber;
    Student(String name, int rollNumber) {
        super(name);  // Invoking superclass constructor
        this.rollNumber = rollNumber;
        System.out.println("Student constructor invoked");
    }
    void display() {
        System.out.println("Name: " + name);
        System.out.println("Roll Number: " + rollNumber);
    }
}
class TechVidvan{
    public static void main(String[] args) {
        Student student = new Student("Alice", 123);
        student.display();
    }
}

Output:

Person constructor invoked
Student constructor invoked
Name: Alice
Roll Number: 123

Explanation:

The Person class has a constructor that takes a name parameter. It initializes the name and prints a message when the constructor is invoked.

The Student class extends Person and has its own constructor that takes both name and rollNumber parameters. It uses the super keyword to invoke the Person constructor to set the name.

The display method in the Student class prints the name and rollNumber of the student.

In TechVidvan, an object of the Student class is created with the name “Alice” and roll number 123, and then the display method is called.

Automatic super() provided by compiler:

If you don’t provide any constructors in your class, the compiler will automatically generate a default constructor which has a super().

This ensures that the superclass is properly initialized before the subclass. This behavior is especially important when you consider that every class implicitly extends the Object class.

If a constructor in a subclass does not have a super(…) or this(…) call, it is assumed to contain an implicit super() call at the beginning.

Automatic super

Example Code:

class Animal {
    Animal() {
        System.out.println("Animal constructor");
    }
}
class Dog extends Animal {
    Dog(){
    // Compiler will insert an implicit super() call here
        System.out.println("Dog constructor");
    }
}
class TechVidvan{
    public static void main(String[] args) {
        Dog dog = new Dog();
    }
}

Output:

Animal constructor
Dog constructor

Summary

In summary, the super keyword promotes proper encapsulation, code organization, and extensibility in object-oriented programming by enabling seamless integration between subclasses and their superclasses in Java.