Effective Java Item16 公開類別中應使用存取方法而非公開欄位
整理 Effective Java 書中 Item 16: In public classes, use accessor methods, not public fields 心得筆記
主旨
公開類別若直接暴露成員欄位(如 public int x
),將會失去封裝帶來的所有好處:無法控制欄位存取、難以變更內部結構、也無法強制不變條件。正確做法是:使用私有欄位,並搭配 public 的 getter / setter 方法進行存取。
問題在哪?直接公開欄位的壞處
上面的設計問題如下:
- 無法在存取欄位時執行額外邏輯(例如驗證、事件觸發)
- 欄位型別或結構若改變(如
double
改成BigDecimal
),會破壞所有使用該欄位的程式碼 - 外部程式可以任意修改欄位內容,導致不可預期的行為
換句話說,欄位的公開等於放棄了封裝。
正確作法:使用 accessor(getter/setter)
好處包括:
- 可以在 setter 加上驗證或額外邏輯
- 保持欄位可控性,減少 bug 機率
- 未來可替換欄位類型或內部儲存方式,只需調整實作,不會影響使用端
例外情況:封裝不必要那麼硬派?
如果類別是:
- package-private(同一個 package 使用)
- private 的 nested class(僅限內部使用)
那麼,適度直接公開欄位是可以接受的。原因是這些類別本來就不會被外部依賴,不會造成「變動影響廣泛」的問題。
這種做法可以減少程式碼冗長,提高可讀性與開發效率。例如:
但如果你哪天把這個類別改成 public
,就必須馬上改為封裝設計。
公開不可變欄位可以嗎?
偶爾會見到這樣的設計:
這樣做的問題不在於欄位會被改動(因為是 final),而是未來你無法輕易變更內部設計,例如將 hour
換成 LocalTime
。只要欄位公開了,你就失去了調整的彈性。
所以,即使欄位是不可變的,也應該預設採取封裝設計。
小結
public
類別絕對不要暴露可變欄位- 即便是不可變欄位,也建議改用 getter
- 想要簡潔可控的程式碼,請善用 private + accessor
- 封裝不是形式,是為了 靈活、可控、可維護
Read other posts