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