6.2 Java 訪問權限修飾詞解析及其應用
訪問權限控制與封裝
- 訪問權限的控制常被稱為具體實作的隱藏,將數據和方法包裝到類別中,以及隱藏具體實作,通常被統稱為封裝
- 訪問權限控制將權限的邊界設定在數據類型的內部
- 設定客戶端程式員可使用與不可使用的界線,避免客戶端意外將內部機制當作可使用的介面
- 將介面與具體的實作進行分離,客戶端除了向介面發送訊息之外什麼也不可以做,這樣可以隨意更改非
public
的部分而不會破壞客戶端程式碼
- 通常為了清晰起見,會採用
public ⇒ protected ⇒ package access ⇒ private
的順序來定義 class,好處是使用者可以從頭讀起並且首先閱讀對他們來說最重要的部分 (由於public
可以被外部調用),遇到非public
成員時便可以停止閱讀
public class OrganizedByAccess {
public void pub1() { /* ... */ }
public void pub2() { /* ... */ }
public void pub3() { /* ... */ }
private void priv1() { /* ... */ }
private void priv2() { /* ... */ }
private void priv3() { /* ... */ }
private int i;
// ...
類別的訪問權限設置 (class access)
- 在 Java 中,訪問權限修飾詞也可以用來確定 library 中哪些 class 對該 library 的使用者來說是可用的
- 為了控制某個 class 的訪問權限,修飾詞要出現在關鍵字
class
之前
package access;
public class Widget {}
- 客戶端可以透過下面的宣告訪問
Widget
import access.Widget;
// 或
import access.*;
- 每個編譯單元 (檔案) 都只能有一個
public
類別,否則編譯器會報錯 public
類別的名稱必須完全與含有該編譯單元的檔案名稱匹配,包含大小寫- 因此對於
Widget
,檔案名稱必須是Widget.java
WIDGET.java
或widget.java
編譯器都會報錯
- 因此對於
- 編譯單元完全不帶
public
類別也是可以的,這情況下可以隨意命名檔案
- 類別不能是
private
或protected
,對於 class 來說,只有 package access 或public
兩種選擇 (內部類別為例外)- 如果不希望任何人對該 class 有訪問權限,可以把 constructor 都指定為
private
- 有一個例外是可以利用該 class 的
static
內部成員創建
- 如果不希望任何人對該 class 有訪問權限,可以把 constructor 都指定為
class Soup1 {
private Soup1() {}
// (1) Allow creation via static method:
public static Soup1 makeSoup() {
return new Soup1();
}
}
class Soup2 {
private Soup2() {}
// (2) Create a static object and return a reference
// upon request.(The "Singleton" pattern):
private static Soup2 ps1 = new Soup2();
public static Soup2 access() {
return ps1;
}
public void f() {}
}
// Only one public class allowed per file:
public class Lunch {
void testPrivate() {
// Can't do this! Private constructor:
//! Soup1 soup = new Soup1();
}
void testStatic() {
Soup1 soup = Soup1.makeSoup();
}
void testSingleton() {
Soup2.access().f();
}
}
Soup1
中創建了一個static
方法,它創建一個新的Soup1
物件並回傳 reference,如果想要做額外的工作,例如紀錄建立了幾個Soup1
物件,這時候很有用Soup2
用到了所謂的設計模式singleton
,你始終只能建立它的一個物件,Soup2
類別的物件是作為Soup2
的一個static private
成員建立的,所以只能有一個,並且除非透過public
方法access()
,否則無法訪問- 如果沒幫類別指定一個訪問修飾符,就會得到預設的 package access,這意味著該類別的物件可以由 package 內任何其他 class 來建立,但 package 外則不行
- 如果該 class 的某個
static
成員為public
,則客戶端仍可以調用該成員,只是不能生成該類別的物件
- 如果該 class 的某個