Java final 關鍵字

final 表示「最終的」,用來限制修改。

final 變數(常數)

final 變數一旦初始化就不能修改:

final int MAX_SIZE = 100;
// MAX_SIZE = 200;  // 錯誤!不能修改

final double PI = 3.14159;
final String APP_NAME = "MyApp";

常數命名慣例

// 靜態常數使用 UPPER_SNAKE_CASE
public static final int MAX_VALUE = Integer.MAX_VALUE;
public static final String DEFAULT_NAME = "Unknown";

// 區域 final 變數可以用 camelCase
final int result = calculate();

final 參數

public void process(final int value) {
    // value = 10;  // 錯誤!不能修改
    System.out.println(value);
}

// 確保方法內不會修改參數
public void copyArray(final int[] source, int[] dest) {
    // source = new int[10];  // 錯誤!
    source[0] = 100;  // OK!可以修改內容,不能修改參考
}

final 與參考型別

對於參考型別,final 限制的是參考,不是物件內容:

final int[] arr = {1, 2, 3};
// arr = new int[5];  // 錯誤!不能指向新陣列
arr[0] = 100;         // OK!可以修改內容

final StringBuilder sb = new StringBuilder("Hello");
// sb = new StringBuilder();  // 錯誤!
sb.append(" World");          // OK!

final 方法

final 方法不能被子類別覆寫:

public class Parent {
    public final void importantMethod() {
        System.out.println("這個方法不能被覆寫");
    }
}

public class Child extends Parent {
    // @Override
    // public void importantMethod() { }  // 錯誤!
}

final 類別

final 類別不能被繼承:

public final class ImmutableClass {
    private final int value;
    
    public ImmutableClass(int value) {
        this.value = value;
    }
    
    public int getValue() {
        return value;
    }
}

// class SubClass extends ImmutableClass { }  // 錯誤!

Java 的 String 就是 final 類別。

blank final

final 變數可以稍後初始化(只能初始化一次):

public class Person {
    private final String name;  // blank final
    
    public Person(String name) {
        this.name = name;  // 在建構子中初始化
    }
}

靜態 blank final

public class Config {
    private static final String DATABASE_URL;
    
    static {
        // 在靜態區塊中初始化
        DATABASE_URL = loadFromConfig();
    }
    
    private static String loadFromConfig() {
        return "jdbc:mysql://localhost:3306/db";
    }
}

實際應用

不可變類別

public final class Money {
    private final int amount;
    private final String currency;
    
    public Money(int amount, String currency) {
        this.amount = amount;
        this.currency = currency;
    }
    
    public int getAmount() {
        return amount;
    }
    
    public String getCurrency() {
        return currency;
    }
    
    // 不提供 setter,物件建立後不可修改
    
    public Money add(Money other) {
        if (!this.currency.equals(other.currency)) {
            throw new IllegalArgumentException("貨幣不同");
        }
        return new Money(this.amount + other.amount, this.currency);
    }
}

工具類別常數

public class HttpStatus {
    public static final int OK = 200;
    public static final int NOT_FOUND = 404;
    public static final int INTERNAL_SERVER_ERROR = 500;
    
    private HttpStatus() {}  // 防止實例化
}

模板方法模式

public abstract class DataProcessor {
    // final 方法定義演算法骨架
    public final void process() {
        readData();
        processData();
        writeData();
    }
    
    protected abstract void readData();
    protected abstract void processData();
    protected abstract void writeData();
}

final 的好處

  1. 安全性:防止意外修改
  2. 執行緒安全:final 欄位是執行緒安全的
  3. 效能:編譯器可以優化
  4. 設計意圖:明確表達不應被修改

何時使用 final

情況建議
常數public static final
不可變欄位private final
不應被覆寫的方法final 方法
不應被繼承的類別final 類別
Lambda 中使用的變數final 或 effectively final