private 是 Java 封裝的**最嚴格層級**:「唯有定義該成員的類別本身,才能存取」。它不僅隔離外部類別,連同套件內的其他類別也擋在門外。本文將詳細說明 private 的精確語意、控制物件建立的經典模式、防止繼承的副作用,以及在多執行緒環境下的關鍵價值。
package-private 截然不同)這使 private 成為「類別內部實作細節」的鐵壁。
將**所有**建構子標記 private,外部無法直接 new,必須透過類別提供的靜態工廠方法:
class Sundae {
private Sundae() {} // 唯一建構子為 private
static Sundae makeASundae() { // 受控建立入口
// 可在此加入:參數驗證、實例池化、建立計數、日誌記錄等
return new Sundae();
}
}
public class IceCream {
public static void main(String[] args) {
// Sundae x = new Sundae(); // 編譯錯誤:建構子私有
Sundae x = Sundae.makeASundae(); // 唯一合法途徑
}
}
access() 回傳Sundae 子類別,呼叫端無感若類別**只有** private 建構子(無 public/protected/package-private 建構子),則**無法被繼承**:
super(),需存取父類別建構子private 建構子不可見 → 子類別無法編譯這是「最終類別」的另一種實現方式(另一種是 final class)。
將輔助方法標記 private 的好處:
書中提到 private 在多執行緒(第 14 章)有「非常重要的用途」,核心在於:
private,只透過 synchronized 方法存取synchronized、Lock、Atomic 還是無鎖演算法,外部不需知情這是 private 從「語法規則」昇華為「併發設計基石」的關鍵。
private 修飾的是**參考變數**,而非物件本身:
class A {
private String secret = "secret";
public String getSecret() { return secret; } // 洩露參考!
}
呼叫端取得 secret 的參考後可修改其內容(若為可變物件)。解決:回傳**防禦性副本**或不可變物件。詳細探討見第 12 章「別名」。
| 場景 | 建議 |
|---|---|
| 預設欄位可見性 | private(資料隱藏) |
| 輔助方法 | private(實作細節) |
| 需給子類別的擴充點 | protected 方法(而非欄位) |
| 套件內協作 | package-private(預設) |
| 對外契約 | public 介面(最小化) |
| 控制建立/單例/池化 | 私有建構子 + 靜態工廠 |
private 是封裝的基石,也是併發安全的第一道防線。養成「預設 private,按需放寬」的習慣,能讓你的類別同時擁有清晰介面、自由重構空間與執行緒安全保障。