| 類型 | 語義 | 初始化位置 |
| 基本類型 | 值不可變 | 聲明處或構造器(二選一) |
| 引用類型 | 引用不可變(指向對象不可改),但對象內部狀態可變 | 同上 |
| 靜態變量 | 類常量,建議大寫下劃線 | 聲明處或靜態塊 |
| 實例變量 | 對象常量,每個實例可不同 | 聲明處或構造器 |
| 局部變量 | 方法內常量 | 首次賦值前必須初始化 |
4. 空白 final 與參數 final
public class Demo {
final int blank; // 空白 final
public Demo(int x) { this.blank = x; } // 構造器初始化
void method(final List list) {
// list = new ArrayList<>(); // 編譯錯誤
list.add("allowed"); // 修改對象內部狀態合法
}
}
二、static:類級別的共享狀態
1. 靜態變量:類加載時初始化,唯一拷貝
- 存儲於方法區(元空間),非堆
ClassName.staticField 訪問,不依賴實例
- 常用於:單例引用、常量、計數器、緩存
2. 靜態方法:無 this,只能訪問靜態成員
- 可通過類名或實例調用(不推薦實例調用)
- 不能訪問實例字段/方法,不能用
this/super
- 不能是
abstract(無實例綁定無法多態)
3. 靜態代碼塊:類加載時按順序執行一次
static { System.out.println("First static block"); }
static { System.out.println("Second static block"); }
- 多塊按聲明順序執行
- 常用於:靜態資源初始化、註冊驅動、原生庫加載
三、static final 組合:全局常量與容器陷阱
public class Constants {
static final String STR = "immutable";
static final List LIST = new ArrayList<>();
}
Constants.LIST.add("mutable!"); // 合法!引用不變,內容可變
// Constants.LIST = new ArrayList<>(); // 編譯錯誤
**核心規則**:static final 修飾容器時,**容器引用不可變,但容器內元素可增刪改**。這是大量工具類(如 Collections.unmodifiableList 之前的手寫不可變集合)的實現基礎。
四、驗證代碼與輸出
public class StaticFinalDemo {
private static final String STR = "aaa";
private static String mutable = null;
private final String instanceFinal = null;
private static final int INT = 0;
private static final Integer OBJ = 8;
private static final List LIST = new ArrayList<>();
public void test() {
System.out.println("---Before---");
printAll();
// STR = "bbb"; // error
mutable = "changed";
// instanceFinal = "x"; // error
// INT = 1; // error
// OBJ = 9; // error
LIST.add("item1"); LIST.add("item2"); // 合法
System.out.println("---After---");
printAll();
}
// ... printAll 省略
}
// 輸出:
// ---Before---
// STR=aaa, mutable=null, instanceFinal=null, INT=0, OBJ=8, LIST=[]
// ---After---
// STR=aaa, mutable=changed, instanceFinal=null, INT=0, OBJ=8, LIST=[item1, item2]
五、面試高頻陷阱總結
- final 參數傳遞:基本類型無意義(值傳遞);引用類型防止引用指向改變,但不防止對象內部修改
- static 方法不可重寫:子類同名靜態方法是**隱藏**而非覆寫,調用由編譯期類型決定
- final 對象引用 vs 對象內容:
final List list = new ArrayList(); list.add(1); // OK
- 類加載順序:父類靜態塊 → 子類靜態塊 → 父類實例塊 → 父構造器 → 子類實例塊 → 子構造器
- 常量池:
static final 基本類型/字符串編譯期進入常量池,調用處直接內聯常量值,**修改常量值需重新編譯所有調用方**
掌握這些細節,不僅能寫出更健壯的代碼,更能在代碼審查與面試中游刃有餘。
- 上一篇文章: Spring 多 Properties 配置文件加載全攻略:五大場景與最佳實踐
- 下一篇文章: Java 多態核心概念與實現原理深度解析
Copyright ©
程式碼之家 All Rights Reserved