final keyword usage in Inheritance

final Keyword Usage in Inheritance:

  1. Final Class:

    • A class declared final cannot be subclassed. You use it to prevent inheritance.

  2. Final Method:

    • A method declared final cannot be overridden by subclasses. It is used when you want to ensure that a particular method’s behavior remains unchanged.

  3. Final Variable:

    • A variable declared final can only be assigned once and cannot be modified after initialization. This is typically used for constants.

When to Use final keyword in Inheritance:

  • To prevent modification: If you don’t want the behavior of a method or class to be altered, declare it as final.

  • For constants: Use final variables to define constants that should remain unchanged, even in subclasses.

  • To create immutable objects: A combination of final classes and final variables can be used to create immutable objects, where the object’s state cannot be altered once created.

1. Final Class

A class declared with the final keyword cannot be subclassed or extended. This means no other class can inherit from it.

  • Usage: You use final for classes when you want to prevent any further inheritance, ensuring that the class’s behavior cannot be modified by subclasses.

// Final class that cannot be extended
final class Animal {
    public void sound() {
        System.out.println("Some generic animal sound");
    }
}

class Elephant extends Animal {  // This will give a compilation error
    public void sound() {
        System.out.println("trumpet");
    }
}

public class Test {
    public static void main(String[] args) {
        Animal animal = new Elephant();
        animal.sound();
    }
}

Another Example:

In this case, a BankAccount class is declared as final so it cannot be extended by any other class. This ensures the security and integrity of the banking logic.

// Final class cannot be extended
final class BankAccount {
    private double balance;

    public BankAccount(double initialBalance) {
        this.balance = initialBalance;
    }

    public void deposit(double amount) {
        balance += amount;
    }

    public void withdraw(double amount) {
        if (amount <= balance) {
            balance -= amount;
        } else {
            System.out.println("Insufficient balance.");
        }
    }

    public void displayBalance() {
        System.out.println("Account balance: " + balance);
    }
}

public class Test {
    public static void main(String[] args) {
        BankAccount account = new BankAccount(1000);
        account.deposit(500);
        account.withdraw(300);
        account.displayBalance();  // Output: Account balance: 1200
    }
}

2. Final Method

A method declared as final cannot be overridden by any subclass. This is useful when you want to maintain the implementation of a method in a superclass, preventing any modification of its behavior in derived classes.

  • Usage: Use final methods when you want to prevent overriding but still want to allow inheritance.

Example

A method such as withdraw is marked as final to prevent subclasses from altering its behavior, which could be dangerous in the context of banking.

class BankAccount {
    private double balance;

    public BankAccount(double initialBalance) {
        this.balance = initialBalance;
    }

    // Final method: Cannot be overridden by subclasses
    public final void withdraw(double amount) {
        if (amount <= balance) {
            balance -= amount;
            System.out.println("Withdrawal successful. Amount: " + amount);
        } else {
            System.out.println("Insufficient balance.");
        }
    }

    public void deposit(double amount) {
        balance += amount;
    }

    public void displayBalance() {
        System.out.println("Account balance: " + balance);
    }
}

class SavingsAccount extends BankAccount {
    public SavingsAccount(double initialBalance) {
        super(initialBalance);
    }

    // Attempting to override the withdraw method will cause a compile-time error
    // public void withdraw(double amount) {
    //     System.out.println("Overridden withdraw method in SavingsAccount");
    // }
}

public class Test {
    public static void main(String[] args) {
        BankAccount account = new BankAccount(1000);
        account.withdraw(200);  // Output: Withdrawal successful. Amount: 200
    }
}

3. Final Variable

A variable declared as final can only be assigned once. Once a final variable is initialized, its value cannot be changed. This is useful when you want to create constants or ensure that certain variables are not modified after initialization.

  • Usage: Use final for constants or fields that should not be reassigned, even if they are inherited by subclasses.

Example

class BankAccount {
    private double balance;
    public final double interestRate = 0.03;  // Final variable to store interest rate

    public BankAccount(double initialBalance) {
        this.balance = initialBalance;
    }

    public void applyInterest() {
        balance += balance * interestRate;
    }

    public void displayBalance() {
        System.out.println("Account balance after interest: " + balance);
    }
}

public class Test {
    public static void main(String[] args) {
        BankAccount account = new BankAccount(1000);
        account.applyInterest();
        account.displayBalance();  // Output: Account balance after interest: 1030.0
    }
}

The final keyword in Java serves as a powerful tool for ensuring immutability, preventing unintended changes, and safeguarding critical components of an application. Here’s a summary of its key uses:

  1. Final Classes: When a class is declared as final, it cannot be subclassed. This is useful when you want to ensure that the behavior of a class remains unchanged and prevent any subclass from modifying its functionality. It ensures security and integrity by protecting the class from inheritance.

  2. Final Methods: A final method cannot be overridden by subclasses. This ensures that specific functionality, particularly critical methods, remains consistent across all instances of the class and its subclasses. It’s a way to protect the integrity of the method’s logic and prevent unauthorized modifications in the inheritance chain.

  3. Final Variables: A final variable can only be assigned once. This guarantees that the value of the variable remains constant throughout its lifetime, making it a great choice for constants or other values that should not change once initialized. It enhances code reliability and prevents accidental changes to important variables.

  4. Control Over Inheritance: By using final, developers can control the inheritance structure in their application, ensuring that specific parts of the code are either not extendable or that crucial methods can’t be overridden, which might compromise their functionality.

  5. Immutability: The final keyword contributes to immutability, a key principle in designing secure and reliable systems. When applied to classes, methods, or variables, final ensures that their state or behavior cannot be altered once set, leading to fewer bugs and better maintainability.

  6. Performance: In some cases, final can also have performance benefits. For example, final methods can be optimized by the Java compiler, as it knows that they won’t be overridden. This can lead to minor performance improvements in some applications.

While the final keyword is a great way to protect classes, methods, and variables from being modified, it should be used judiciously. Overusing it may make code harder to extend or modify in the future. However, when used appropriately, final ensures code stability, consistency, and security, making it an essential tool for Java developers.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top