Unlock Your Python Backend Career: Build 30 Projects in 30 Days. Join now for just $54

Object-Oriented Programming

Java Backend Development: Zero to Hero

Object-Oriented Programming

Understanding static, final, super, super(), this() and this

Understanding static, final, super, super(), this() and this

The 'final' Keyword in Java.pngFinal

  • final is a keyword that can be used with classes, methods, and variables.

  • To declare a constant variable, use the final keyword. The value of a final variable cannot be changed once assigned.

  • If a class is marked as final, it cannot be inherited by any other class.

  • If a method is declared as final, it cannot be overridden in any subclass.

  • Global final variables are initialized at the time of declaration, while local final variables can be declared first and initialized later, but only once.

Syntax

final DataType variableName = value;


final ReturnType methodName(Parameters) {
    // method body
}

final class ClassName {
    // class body
}

Example

final class FinalClass {
    final int finalVariable = 100;

    final void finalMethod(final int param) {
        System.out.println("Inside finalMethod");
        System.out.println("Final variable value: " + finalVariable);
        System.out.println("Final parameter value: " + param);
    }
}

public class MasteringBackend {
    public static void main(String[] args) {
        FinalClass obj = new FinalClass();
        obj.finalMethod(50);
    }
}

In this example, we declare the class as final, which means it cannot be inherited. We also make the variable final, so its value cannot be changed. Also, the method is marked as final, preventing it from being overridden in any subclass.

Output

Inside finalMethod
Final variable value: 100
Final parameter value: 50

Static

The 'static' Keyword in Java.png

  • static is a keyword that can be used to declare variables, methods, and nested classes.

  • The static keyword is used for memory management. When a variable is declared as static, only one copy of that variable is created, and it is shared among all instances of the class.

image (25).pngExample - If the name of a company is declared as static, such as Mastering Backend, then all team members will reference the same company name. If the company name is rebranded, you only need to change it in one place, and it reflects everywhere.

  • Static members of the class are related to the class itself, so we access these directly using the class name.

  • A static block is automatically executed when the class is loaded.

  • Static members of the class cannot participate in inheritance.

  • Static members can be accessed directly from a static context.

  • Static members can also be accessed directly from a non-static context.

Syntax

static DataType variableName;

static ReturnType methodName(Parameters) {
    // method body
}

static {
    // static initialization code
}

class OuterClass {
    static class NestedClass {
        // class body
    }
}


// Access the method and variable with class name
ClassName.staticVariable;
ClassName.staticMethod();

// Access the Inner class with outer class name
OuterClass.NestedClass nestedObj = new OuterClass.NestedClass();
nestedObj.methodName();

We can declare a method, a block, a variable, and even an inner class as static.

Example

public class BankAccount {
    private int accountNumber;
    private double balance;

    static double interestRate;      
    static int totalAccounts = 0;   

    static {
        System.out.println("Bank system initialized.");
        interestRate = 4.5; 
    }

    public BankAccount(int accountNumber, double initialDeposit) {
        this.accountNumber = accountNumber;
        this.balance = initialDeposit;
        totalAccounts++;
    }

    public void displayAccountDetails() {
        System.out.println("Account No: " + accountNumber);
        System.out.println("Balance: $" + balance);
        System.out.println("Interest Rate: " + interestRate + "%");
    }

    public static void setInterestRate(double newRate) {
        interestRate = newRate;
    }

    public static void showTotalAccounts() {
        System.out.println("Total Bank Accounts: " + totalAccounts);
    }

    public static void main(String[] args) {
        BankAccount acc1 = new BankAccount(101, 5000);
        BankAccount acc2 = new BankAccount(102, 10000);

        acc1.displayAccountDetails();
        acc2.displayAccountDetails();

        BankAccount.setInterestRate(5.0); 

        System.out.println("\nAfter updating interest rate:");
        acc1.displayAccountDetails();
        acc2.displayAccountDetails();

        BankAccount.showTotalAccounts(); 
    }
}

In this example, the static block is executed first because static blocks run as soon as the class is loaded into memory. The static double interestRate is shared across all accounts, which is why it is declared as static. Similarly, static int totalAccounts is used to keep track of the total number of accounts, and it is also marked as static.

To access these static members, we do not need to create an object of the class. They can be called directly using the class name.

Bank system initialized.
Account No: 101
Balance: $5000.0
Interest Rate: 4.5%
Account No: 102
Balance: $10000.0
Interest Rate: 4.5%

After updating interest rate:
Account No: 101
Balance: $5000.0
Interest Rate: 5.0%
Account No: 102
Balance: $10000.0
Interest Rate: 5.0%
Total Bank Accounts: 2

this Keyword

  • this is a keyword in Java.

  • It is a reference variable that refers to the current object, the object whose method or constructor is being called.

  • It helps to resolve ambiguity between instance variables and parameters with the same name.

    • For example, if the instance variable and the parameter of a constructor or method share the same name, this is used to distinguish between them.

public class Student {
    String name;
    int age;

    // Constructor
    public Student(String name, int age) {
        this.name = name; 
        this.age = age;
    }

    public void displayInfo() {
        System.out.println("Name: " + this.name); // Optional use
        System.out.println("Age: " + this.age);
    }

    public static void main(String[] args) {
        Student s1 = new Student("Ayush", 22);
        s1.displayInfo();
    }
}

In this example, name and age are the instance variables of the class, whereas name and age are also parameters of the constructor. That's why we use the this keyword, which refers to the current object.

Output

Name: Ayush
Age: 22
  • this keyword is used to invoke the current class method.

public class Student {
    String name;
    int age;

    

    // Method to display student info
    public void display() {
        System.out.println("Name: " + name + ", Age: " + age);
    }

    // Method to invoke display using this keyword
    public void showDetails() {
        this.display(); // calling display() method using this
    }

    public static void main(String[] args) {
      

     

        Student s2 = new Student("Ayush", 22); // Calls parameterized constructor
        s2.showDetails();                      // Calls display using this
    }
}

Here, the showDetails() method of the class is calling the display() method with the help of the this keyword. When we create the object of the class, the default constructor is called. Then, when we call the showDetails() method, it triggers the display() method because of the this keyword.

Output


Name: Ayush, Age: 22

this()

  • this() calling statement is used to call the current class constructor.

  • this() call must always be written inside a constructor.

  • this() statement must always be the first line inside the constructor.

Syntax

this();

this(parameter1.......);

In this example, the default constructor of the class is calling the parameterized constructor with the help of the this() calling statement, passing the same number of parameters.

public class Student {
    String name;
    int age;

    // Constructor 1: Default constructor
    public Student() {
        this("Unknown", 0); 
        System.out.println("Default constructor called");
    }

    // Constructor 2: Parameterized constructor
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("Parameterized constructor called");
    }

   

   public static void main(String[] args) {
        Student s1 = new Student();    // Calls default constructor
        s1.showDetails();              // Calls display using this

  
    }
}

Output

Parameterized constructor called
Default constructor called
  • with the help of the this keyword we can return the object of the current class.

public class Student {
    String name;
    int age;

    // Method to set name
    public Student setName(String name) {
        this.name = name;
        return this; // returns current object
    }

    // Method to set age
    public Student setAge(int age) {
        this.age = age;
        return this; // returns current object
    }

    // Method to display student details
    public void display() {
        System.out.println("Name: " + name + ", Age: " + age);
    }

    public static void main(String[] args) {
        Student student = new Student();

        // Method chaining using 'this'
        student.setName("Ayush").setAge(22).display();
    }
}

Output

Name: Ayush, Age: 22

Constructor Chaining

Constructor chaining means calling one constructor from another constructor in the same class using the this() keyword.

image (26).pngIn this image, one constructor is calling the next constructor, creating a chain of constructor calls.

Example

public class Student {
    String name;
    int age;
    String course;
    String college;

    // Constructor 1: No-arg constructor
    public Student() {
        this("Ayush"); // Calls Constructor 2
        System.out.println("Constructor 1: No-arg constructor");
    }

    // Constructor 2: One-arg constructor
    public Student(String name) {
        this(name, 22); // Calls Constructor 3
        System.out.println("Constructor 2: Name = " + name);
    }

    // Constructor 3: Two-arg constructor
    public Student(String name, int age) {
        this(name, age, "Computer Science"); // Calls Constructor 4
        System.out.println("Constructor 3: Name = " + name + ", Age = " + age);
    }

    // Constructor 4: Three-arg constructor
    public Student(String name, int age, String course) {
        this.name = name;
        this.age = age;
        this.course = course;
        this.college = "XYZ University";
        System.out.println("Constructor 4: Name = " + name + ", Age = " + age + ", Course = " + course + ", College = " + college);
    }

    public static void main(String[] args) {
        Student s = new Student(); // Starts constructor chain
    }
}

In this example, when we create an object of the Student class using Student s = new Student();, the constructor chain starts from the no-argument constructor. Inside this constructor, the line this("Ayush"); is executed, which calls the one-argument constructor public Student(String name).

Inside the one-argument constructor, the line this(name, 22); is executed, which calls the two-argument constructor public Student(String name, int age).

Next, inside the two-argument constructor, the line this(name, age, "Computer Science"); is executed, which calls the three-argument constructor public Student(String name, int age, String course).

Finally, the three-argument constructor initializes all the instance variables and prints the final message.

After the deepest constructor completes its execution, control returns back up the chain, and each constructor prints its message in reverse order of the call stack.

Output

Constructor 4: Name = Ayush, Age = 22, Course = Computer Science, College = XYZ University
Constructor 3: Name = Ayush, Age = 22
Constructor 2: Name = Ayush
Constructor 1: No-arg constructor

'super' and 'this' Keywords in Java.pngSuper Keyword

  • super is a reference variable that is similar to the this keyword, but it is used to refer to the immediate parent class object.

  • When an instance of a subclass is created, an instance of its parent class is also created implicitly, which which is referred by super reference variable.

  • The super keyword is used to call the immediate parent class's instance variables.

  • It is also used to invoke the parent class's methods in subclasses.

Syntax

super.methodName();

Example

class Parent {
    void show() {
        System.out.println("This is Parent class method");
    }
}

class Child extends Parent {
    void show() {
        System.out.println("This is Child class method");
    }

    void display() {
        super.show(); // Calls Parent class show()
        show();       // Calls Child class show()
    }
}

public class Main {
    public static void main(String[] args) {
        Child obj = new Child();
        obj.display();
    }
}

In this example, we are calling the superclass method show() from within the child class. When we create an object of the subclass, the superclass object is implicitly created as well. So, when we call the subclass method display(), the line super.show(); is executed, which calls the parent class method.

Output

This is Parent class method
This is Child class method

super keyword is used to invoke the immediate parent class's variables from within the subclass.

Syntax

super.variableName;

Example

class Parent {
    int x = 100;
}

class Child extends Parent {
    int x = 200;

    void display() {
        System.out.println("Child x: " + x);         // refers to Child's x
        System.out.println("Parent x: " + super.x);  // refers to Parent's x
    }
}

public class Main {
    public static void main(String[] args) {
        Child obj = new Child();
        obj.display();
    }
}

In this example, we are calling the superclass variable x in the subclass. When we create the object of the subclass, the superclass object is implicitly created. So, when we access the variable x from the subclass, the line x = 100 is executed, and the parent class variable is accessed, resulting in the expected output.

Output

Child x: 200
Parent x: 100

super()

  • super() calling statement is similar to this(), but super() is used to call the immediate parent class constructor.

  • Like the this keyword, it is used inside the constructor.

  • super() statement must always be written as the first line in the constructor.

Syntax

super(); // Calls the no-argument constructor of the parent class

super(arguments); // Calls the parameterized constructor of the parent class

Example

class Parent {
    Parent() {
        System.out.println("Parent class constructor");
    }
}

class Child extends Parent {
    Child() {
        super(); // Optional here as it is called implicitly
        System.out.println("Child class constructor");
    }
}

public class Main {
    public static void main(String[] args) {
        Child obj = new Child();
    }
}

In this example when we create the object of child class, the parent class constructor is implicitly called.

Output

Parent class constructor
Child class constructor

Example

class Parent {
    Parent(String name) {
        System.out.println("Parent class constructor with name: " + name);
    }
}

class Child extends Parent {
    Child() {
        super("Ayush"); // Calls Parent constructor with argument
        System.out.println("Child class constructor");
    }
}

public class Main {
    public static void main(String[] args) {
        Child obj = new Child();
    }
}

In this example, when we create an object of the subclass, the superclass object is implicitly created, which in turn invokes the superclass methods. Here, we are specifically invoking the parameterized constructor of the superclass from the subclass using the super() calling statement.

Output

Parent class constructor with name: Ayush
Child class constructor

Constructor chaining means calling one constructor from another. When using super(), it chains constructors from subclass to superclass.

Example

class Parent {
    Parent() {
        System.out.println("Parent constructor");
    }
}

class Child extends Parent {
    Child() {
        super(); // Calls Parent constructor (constructor chaining)
        System.out.println("Child constructor");
    }
}

public class Main {
    public static void main(String[] args) {
        new Child();
    }
}

Here in this example Parent-to-child constructor chaining is present.

Output

Parent constructor
Child constructor

Whenever you're ready

There are 4 ways we can help you become a great backend engineer:

The MB Platform

Join 1000+ backend engineers learning backend engineering. Build real-world backend projects, learn from expert-vetted courses and roadmaps, track your learnings and set schedules, and solve backend engineering tasks, exercises, and challenges.

The MB Academy

The “MB Academy” is a 6-month intensive Advanced Backend Engineering BootCamp to produce great backend engineers.

Join Backend Weekly

If you like post like this, you will absolutely enjoy our exclusive weekly newsletter, Sharing exclusive backend engineering resources to help you become a great Backend Engineer.

Get Backend Jobs

Find over 2,000+ Tailored International Remote Backend Jobs or Reach 50,000+ backend engineers on the #1 Backend Engineering Job Board