Java final and Inheritance: Learn final Classes, Methods, and Variables

0

Inheritance is designed to allow classes to extend and specialize existing behavior. But what if a class designer wants to prevent certain parts of that behavior from being changed? Java provides the final keyword to place exactly these restrictions.

When used with inheritance, final can prevent a class from being extended or prevent a method from being overridden. A final field has a related but different purpose: it prevents reassignment of that variable.

In inheritance, final can stop further inheritance or method overriding. It is a way to deliberately protect a design from modification through subclasses.

final Class Cannot Be Extended

When a class is declared with final, another class cannot extend it.

final class SecurityManager {
    void checkAccess() {
        System.out.println("Access checked");
    }
}

// Compile-time error
class CustomManager extends SecurityManager {
}

The compiler rejects the subclass because SecurityManager has explicitly declared that it cannot participate as a parent class.

final class means "this class cannot have subclasses."

Why Make a Class final?

A class may be made final when its behavior should not be changed through inheritance. This can be useful when extending the class could violate important design assumptions, security rules, or invariants.

A familiar example from the Java API is String, which is final. This prevents developers from creating subclasses of String that could alter its established behavior.

final Method Cannot Be Overridden

A class does not have to be completely final to protect a particular method. You can mark an individual method as final.

class Employee {
    final void companyPolicy() {
        System.out.println("Company policy is fixed");
    }
}

class Developer extends Employee {
    // Compile-time error
    // void companyPolicy() { }
}

The Developer class can still extend Employee and add its own methods, but it cannot replace the final companyPolicy() implementation.

A final method can be inherited, but it cannot be overridden.

final Field Is Different

The final keyword can also be applied to variables and fields. In that context, it means the variable cannot be assigned a new value after it has been initialized.

class Employee {
    final int employeeId = 101;

    void display() {
        System.out.println(employeeId);
    }
}

The field can be read, but attempting to assign another value to it will produce a compile-time error.

So, do not confuse a final field with a final method or final class. The effect of final depends on what it is applied to.

Declaration Effect Inheritance Impact
final variable Cannot be reassigned after initialization. Does not prevent inheritance by itself.
final method Cannot be overridden. Child classes may inherit it but cannot replace it.
final class Cannot be extended. No subclass can be created.

final Method and Method Overriding

Remember that overriding allows a child class to replace inherited instance behavior. Declaring the method final tells Java that replacement is not allowed.

class Vehicle {
    final void startSafetyCheck() {
        System.out.println("Safety check completed");
    }

    void drive() {
        System.out.println("Vehicle is driving");
    }
}

class Car extends Vehicle {
    @Override
    void drive() {
        System.out.println("Car is driving");
    }

    // Cannot override startSafetyCheck()
}

This is a useful design pattern: allow subclasses to customize some behavior while keeping critical behavior fixed.

final Does Not Mean the Object Is Immutable

Another common misconception is that declaring a reference variable final automatically makes the referenced object immutable. It does not.

final StringBuilder builder = new StringBuilder("Java");

builder.append(" Programming");

// builder = new StringBuilder("New");
// Not allowed: the reference cannot be reassigned

The reference cannot point to another object, but the object itself may still be mutable. This distinction becomes important when designing classes and APIs.

Can a final Class Be Used as a Parent Reference?

A final class cannot be extended, but it can still be instantiated and its objects can be referenced normally.

final class Report {
    void generate() {
        System.out.println("Report generated");
    }
}

public class Main {
    public static void main(String[] args) {
        Report report = new Report();

        report.generate();
    }
}

The restriction is specifically about inheritance. Declaring a class final does not make the class unusable.

Common Beginner Mistakes

  • Thinking a final class cannot be instantiated.
  • Thinking a final method cannot be inherited.
  • Assuming final automatically makes an object immutable.
  • Confusing a final variable with a final class.
  • Trying to override a final method.

Best Practice

Use final when you have a clear design reason to prevent extension, overriding, or reassignment. It communicates an intentional constraint to both the compiler and other developers.

Do not mark everything final simply because it is possible. The goal is to make important design boundaries explicit while leaving legitimate extension points open.

Interview Insight

A strong interview answer is: "A final class cannot be extended, a final method cannot be overridden, and a final variable cannot be reassigned after initialization. In inheritance, final is commonly used to restrict subclassing or prevent modification of specific inherited behavior."

Final Takeaway

The final keyword gives Java developers a precise way to control inheritance. A final class closes the inheritance door completely, a final method protects a particular implementation from overriding, and a final variable prevents reassignment. Understanding these three meanings helps you design class hierarchies that are flexible where they should be and protected where they must be.

Post a Comment

0Comments
Post a Comment (0)