☕ Java Q11 / 105

Explain final keyword in Java.

AI-Powered Answer ✓ Answered

The `final` keyword in Java is a non-access modifier that restricts modification, overriding, or inheritance, depending on where it's applied. It signifies immutability or a lack of extensibility.

Purpose of `final`

The final keyword in Java is used to define an entity that cannot be reassigned (for variables), overridden (for methods), or inherited (for classes). It's a powerful tool for ensuring immutability and enforcing design constraints, helping to create more robust and secure code.

Applying `final`

final can be applied to variables, methods, and classes, each with a distinct effect.

`final` Variables

When applied to a variable, final makes it a constant, meaning its value can only be assigned once. For primitive types, this means the value itself cannot change. For reference types, it means the reference itself cannot be reassigned to point to a different object, although the internal state of the referenced object can still be modified (unless the object itself is immutable).

java
public class FinalVariableExample {
    // Compile-time constant
    private final int MAX_VALUE = 100;

    // Blank final variable, must be initialized in constructor
    private final String API_KEY;

    public FinalVariableExample(String apiKey) {
        this.API_KEY = apiKey; // Assigned once
        // MAX_VALUE = 200; // Compile-time error: cannot assign a value to final variable MAX_VALUE
    }

    public void demonstrate() {
        final int localConstant = 50;
        // localConstant = 60; // Compile-time error
        System.out.println("Max Value: " + MAX_VALUE);
        System.out.println("API Key: " + API_KEY);

        final StringBuilder sb = new StringBuilder("Hello");
        // sb = new StringBuilder("World"); // Compile-time error: cannot assign a value to final variable sb
        sb.append(" World"); // This is allowed, the object's state can change
        System.out.println("StringBuilder: " + sb);
    }
}

`final` Methods

A final method cannot be overridden by any subclass. This is useful for preventing unwanted modifications to core logic, ensuring that a method's implementation remains consistent across the class hierarchy. It's often used in design patterns or utility classes where specific behavior should not be altered.

java
class Parent {
    public final void display() {
        System.out.println("This is a final method in Parent.");
    }

    public void greet() {
        System.out.println("Hello from Parent!");
    }
}

class Child extends Parent {
    // @Override
    // public void display() { // Compile-time error: cannot override final method from Parent
    //     System.out.println("This is a display method in Child.");
    // }

    @Override
    public void greet() { // Allowed, greet is not final
        System.out.println("Hello from Child!");
    }
}

`final` Classes

When a class is declared as final, it cannot be extended or subclassed. This means no other class can inherit from it. final classes are inherently immutable (if their fields are also final and properly handled) and are often used for security reasons, to prevent malicious subclasses, or to create utility classes with fixed behavior, like String, Integer, and other wrapper classes in Java's standard library.

java
final class ImmutablePoint {
    private final int x;
    private final int y;

    public ImmutablePoint(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() { return x; }
    public int getY() { return y; }

    // No setters, ensuring immutability
}

// class AnotherPoint extends ImmutablePoint { // Compile-time error: cannot inherit from final ImmutablePoint
//     // ...
// }

Summary

  • final variables: Can be assigned only once, making them constants. For reference types, the reference cannot change, but the object's state might (unless the object itself is immutable).
  • final methods: Cannot be overridden by subclasses, ensuring consistent behavior.
  • final classes: Cannot be extended or inherited, preventing modification of their behavior through subclassing.
  • Used for immutability, security, and enforcing design constraints.