Java Final Keyword

The final keyword in Java is used to declare constants, prevent method overriding, and prevent inheritance. It can be applied to variables, methods, and classes to restrict their behavior in different ways. Here’s a detailed explanation of how the final keyword works and where it can be used in Java.

final with Variables (Constant Variables)

When the final keyword is applied to a variable, it indicates that the variable’s value cannot be changed once it has been initialized. The variable is treated as a constant.

Rules for final variables:

1. Primitive types: The value of a final primitive variable cannot be changed once it is initialized.

2. Reference types (Objects): The reference to the object cannot be changed, but the object’s state (its fields or properties) can still be modified (if not marked final).

Example:


// Main.java file
class UploadFile {
    // final primitive variable
    final int MAX_FILE_UPLOAD_SIZE = 10; //10 MB
    
    // final reference variable (cannot point to another object)
    final String fileName = "Complete Java";

    public void changeValues() {
        // Uncommenting the next lines will cause compile-time errors
        // MAX_LIMIT = 20;  // Error: cannot assign a value to a final variable
        // name = "Complete Python";   // Error: cannot assign a value to a final variable
    }

}

public class Main {
     public static void main(String[] args) {
        UploadFile uploadFile = new UploadFile();
        System.out.println("MAX_FILE_UPLOAD_SIZE: " + uploadFile.MAX_FILE_UPLOAD_SIZE);  // 10
        System.out.println("name: " + uploadFile.fileName);  // Complete Java
    }
}

Explanation:

  1. The variable MAX_FILE_UPLOAD_SIZE is declared final, so it cannot be reassigned after it has been initialized to 10.
  2. The fileName variable is also final. It cannot point to another object once initialized, but if it were an object with mutable fields, those fields could still be changed.

final with Methods (Preventing Method Overriding)

When the final keyword is used in front of a method, it prevents that method from being overridden by any subclass. This ensures that the behavior of the method remains fixed and cannot be changed by a subclass.

Note: You cannot override a final method in a subclass.

Example:


// Main.java file
class Animal {
    // final method cannot be overridden
    public final void makeSound() {
        System.out.println("Animal makes a sound");
    }
}

class Dog extends Animal {
    // Uncommenting the next line will cause a compile-time error
    // public void makeSound() {  // Error: Cannot override the final method from Animal
    //     System.out.println("Dog barks");
    // }
}

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.makeSound();  // Output: Animal makes a sound
    }
}

Explanation:

  1. The method makeSound() in the Animal class is declared as final, meaning it cannot be overridden in the Dog subclass. Attempting to override it will result in a compile-time error.
  2. The Dog class cannot provide its own implementation of makeSound(), so it uses the implementation from the Animal class.

final with Classes (Preventing Inheritance)

When a class is declared final, it cannot be subclassed (i.e., no other class can extend it). This is useful when you want to prevent any further inheritance of that class and ensure its behavior remains unchanged.

A final class cannot be extended by any subclass.

Example:


final class Animal {
    // final method cannot be overridden
    public final void makeSound() {
        System.out.println("Animal makes a sound");
    }
}
// Uncommenting the next class will cause a compile-time error
// can't extend final class
//class Dog extends Animal {
    // public void makeSound() {  
    //     System.out.println("Dog barks");
    // }
//}

public class Main {
    public static void main(String[] args) {
        Animal animal = new Animal();
        animal.makeSound();  // Output: Animal makes a sound
    }
}

Explanation:

  1. The class Animal is declared as final, meaning it cannot be extended. If you try to create a subclass (Dog), the compiler will throw an error.
  2. This ensures that the Animal class cannot be modified by subclassing.

final with Method Parameters

The final keyword can also be used with method parameters. When a parameter is declared as final, its value cannot be changed within the method body. This ensures that the parameter remains constant throughout the method execution.

Example: final with Method Parameters


//Main.java file
class Calculator {
    public void add(final int a, final int b) {
        // a = 50;  // Error: Cannot assign a value to final variable a
        // b = 70;  // Error: Cannot assign a value to final variable b
        System.out.println("Sum: " + (a + b));
    }
}

public class Main{
     public static void main(String[] args) {
        Calculator calc = new Calculator();
        calc.add(10, 20);  // Output: Sum: 30
    }
}

Explanation:

In the add() method, the parameters a and b are declared final, which means their values cannot be modified inside the method. Attempting to modify them will result in a compile-time error.