Effective Java Item17 最小化可變性
整理 Effective Java 書中 Item 17: Minimize mutability 心得筆記
主旨
當你設計類別時,預設應該先問自己:這個物件真的需要改變狀態嗎?如果不需要,請讓它不可變(Immutable)。不可變類別更安全、更好測試、也更容易被重用與快取。
如何設計不可變類別?
只要遵守這五個原則就能做到:
- 不提供修改狀態的方法(setter)
- 類別設為
final
(禁止被繼承) - 所有欄位設為
private final
- 不讓外部取得內部可變物件(防守性複製)
- 建構後物件狀態固定
✅ 範例:一個不可變的 User
這個 User
類別一旦建立,就無法修改 name 與 age,也沒有任何 setName()
或 setAge()
方法,這就是不可變類別的基本形式。
為什麼要這麼做?
- 簡單安全:狀態不會變,就不會出錯
- 天然支援多執行緒:不需要同步鎖
- 適合當 Map 的 key、Set 的元素
- 更容易被快取或共用:例如
String
就是不可變的
✅ 好處延伸:可提供常用值常數
例外狀況:真的很需要變的情況
如果你要表示一個計數器的狀態或畫面中物件的位置,可能就需要可變類別。但即使如此,也應盡量限制可變範圍。
這裡的 Counter
是可變的,但它的可變行為是被控制住的,只有 increment()
可以改變狀態,這也是最小化可變性的一種方式。
避免的狀況:過度暴露狀態
以下寫法就違反了不可變原則,讓外部可以直接修改欄位:
只要任何人能自由改動物件狀態,這個類別就變得難以維護、容易出錯,也難以保證資料一致性。
小結
- ✅ 如果不需要修改狀態,就做成不可變
- ✅ 所有欄位設為
private final
- ✅ 沒有 setter,只保留 getter
- ✅ 必要時可提供 companion 類別(如
StringBuilder
對應String
)
不可變類別是好習慣的起點,也能減少維護成本與意外行為,是穩健程式設計的基石。
Read other posts