final Keyword

Constants and immutability

5 min read

final Keyword in Java

The final keyword means "cannot be changed". It can be applied to variables, methods, and classes, each with different implications.

final Applied To

  • Variable: Value cannot be changed after initialization
  • Method: Cannot be overridden by subclasses
  • Class: Cannot be extended (no subclasses)

🔑 Important: final variable = reference cannot change. For objects, the reference is constant but the object's internal state can still change!

💡 Convention: Final constants use UPPER_SNAKE_CASE: final int MAX_SIZE = 100;

Code Examples

Final variables and constants

java
1// Final Variables (Constants)
2public class Constants {
3    // Compile-time constant
4    public static final int MAX_USERS = 1000;
5    public static final String APP_NAME = "MyApp";
6    public static final double PI = 3.14159;
7    
8    // Instance final - set once per object
9    private final String id;
10    
11    public Constants(String id) {
12        this.id = id;  // Must initialize in constructor
13    }
14}
15
16// Final local variable
17public void process(int x) {
18    final int y = x * 2;  // Cannot reassign
19    // y = 10;  // ERROR!
20    
21    // Final parameter
22    final String message = "Hello";
23    // message = "Bye";  // ERROR!
24}
25
26// Blank final - initialize in constructor
27public class User {
28    private final String name;  // Blank final
29    
30    public User(String name) {
31        this.name = name;  // Must initialize here
32    }
33}

Final reference vs final object state

java
1// Final with Objects - REFERENCE is final, not object
2public class FinalReference {
3    public static void main(String[] args) {
4        final List<String> list = new ArrayList<>();
5        
6        // Cannot reassign reference
7        // list = new ArrayList<>();  // ERROR!
8        
9        // But CAN modify the object!
10        list.add("Hello");    // OK!
11        list.add("World");    // OK!
12        list.clear();         // OK!
13        
14        System.out.println(list);  // [Hello, World] before clear
15        
16        // Final array
17        final int[] arr = {1, 2, 3};
18        // arr = new int[5];  // ERROR! Can't reassign
19        arr[0] = 100;         // OK! Can modify contents
20        
21        // To make truly immutable, use:
22        final List<String> immutable = List.of("A", "B", "C");
23        // immutable.add("D");  // UnsupportedOperationException!
24    }
25}

Final methods prevent overriding

java
1// Final Methods - Cannot be overridden
2public class Parent {
3    // Final method - locked implementation
4    public final void criticalMethod() {
5        System.out.println("Cannot be overridden");
6    }
7    
8    // Non-final - can be overridden
9    public void normalMethod() {
10        System.out.println("Can be overridden");
11    }
12}
13
14public class Child extends Parent {
15    // ERROR: Cannot override final method
16    // public void criticalMethod() { }
17    
18    // OK: Can override non-final
19    @Override
20    public void normalMethod() {
21        System.out.println("Overridden!");
22    }
23}
24
25// Common use: Template Method Pattern
26public abstract class DataProcessor {
27    // Final template - preserves algorithm structure
28    public final void process() {
29        readData();
30        validateData();
31        transform();
32        save();
33    }
34    
35    // Subclasses implement these
36    protected abstract void readData();
37    protected abstract void transform();
38    protected abstract void save();
39    protected void validateData() {}  // Default implementation
40}

Final classes cannot be extended

java
1// Final Classes - Cannot be extended
2public final class String {
3    // No one can extend String class
4}
5
6// ERROR: Cannot extend final class
7// class MyString extends String { }
8
9// Java final classes examples:
10// - String
11// - Integer, Double, Boolean (wrapper classes)
12// - Math
13// - System
14
15// When to use final class
16// 1. Security - prevent malicious subclasses
17public final class SecurityManager {
18    public void checkPermission() {
19        // Critical security logic
20    }
21}
22
23// 2. Immutable classes
24public final class ImmutablePoint {
25    private final int x;
26    private final int y;
27    
28    public ImmutablePoint(int x, int y) {
29        this.x = x;
30        this.y = y;
31    }
32    
33    public int getX() { return x; }
34    public int getY() { return y; }
35}
36
37// 3. Utility classes
38public final class StringUtils {
39    private StringUtils() {}  // Private constructor
40    
41    public static boolean isEmpty(String s) {
42        return s == null || s.isEmpty();
43    }
44}

Use Cases

  • Creating constants
  • Preventing method overriding
  • Creating immutable classes
  • Security-critical code
  • Thread safety (final fields)
  • API stability

Common Mistakes to Avoid

  • Thinking final object is immutable
  • Not initializing blank final in constructor
  • Overusing final on everything
  • Using final where interface would be better
  • Confusing final with static
  • Final parameter in method rarely useful