在 Java 中,所有類、接口、字段、方法、構造器都受訪問權限控制。權限層級從大到小依次為:public > protected > 包訪問權限(默認,無關鍵字) > private。合理使用權限修飾符是實現封裝、隱藏實現細節、降低耦合的關鍵。
無關鍵字修飾即為包訪問權限。同包類之間可自由互訪,外包類視為 private。這將功能相關的類組合成內聚模塊。
注意:無包聲明的類屬於默認包,同目錄下無包聲明的類互享包訪問權限。
// Cake.java 與 Pie.java 同目錄、無包聲明
class Pie { void f() { System.out.println("Pie.f()"); } }
public class Cake {
public static void main(String[] args) {
new Pie().f(); // 輸出:Pie.f()
}
}
public 成員對所有人可見,構成類對外的 API 契約。設計時應謹慎暴露,避免內部實現細節洩露為公共接口。
private 成員僅當前類可訪問,連同包、子類均不可見。核心用途:
class Sundae {
private Sundae() {} // 禁止外部直接構造
static Sundae makeASundae() { return new Sundae(); } // 工廠方法控制創建
}
public class IceCream {
public static void main(String[] args) {
Sundae x = Sundae.makeASundae(); // 僅能通過靜態工廠獲取實例
}
}
陷阱提醒:某對象引用為 private 不代表其他對象無法持有該對象的 public 引用(引用傳遞特性)。
protected = 包訪問權限 + 子類繼承訪問(跨包也可)。適用於:基類設計者希望特定成員對派生類開放,但對外部類隱藏。
訪問控制將「客戶端可用」與「內部實現」劃清界限,雙重意義:
將數據與方法封裝進類、隱藏具體實現,統稱封裝。
頂層類只能是 public 或包訪問權限(不可 private/protected,內部類除外)。
public class:文件名必須與類名完全一致(含大小寫),每個編譯單元僅一個public 類// 方案一:靜態工廠方法
class Soup1 {
private Soup1() {}
public static Soup1 makeSoup() { return new Soup1(); }
}
// 方案二:單例模式
class Soup2 {
private Soup2() {}
private static Soup2 ps1 = new Soup2();
public static Soup2 access() { return ps1; }
public void f() {}
}
public class Lunch {
void testPrivate() { /* new Soup1(); 編譯錯誤 */ }
void testSingleton() { Soup2.access().f(); }
}
private,按需放寬private,通過公共方法訪問(保留驗證/擴展彈性)publicprotected 僅用於設計繼承體系時的模板方法/鉤子方法