作者在前面章節簡單介紹過訪問權限控制的內容,前面《Java編程思想筆記一:基本概念》也有列出。Java 訪問權限控制的等級從大到小依次是:public、protected、包訪問權限(沒有關鍵詞)和 private。
一、包權限
一個 Java 源代碼文件即一個 .java 文件,通常被稱為編譯單元(有時也稱轉譯單元),在一個編譯單元內最多只可以有一個 public 類,且該類名稱必須與文件名相同。
包其實是一個庫的單元,類庫實際是一組文件,某個文件都有一個 public 類,以及任意數量的非 public 類。因此每個文件都有一個構件(每一個都有它們自己的獨立的 .java 和 .class 文件),如果希望這些構件從屬于同一個群組,就可以使用關鍵字 package。
包名
如果你的項目引用了項目 A 和 B,但是二者都有一個 tool 包,你的項目在使用 tool 包時就會出現包名沖突的問題,你必須通過某些額外的一些手段去解決。
為了有效避免包名沖突的問題,同時也為了更直觀地管理一個包下面的所有 .class 文件,Java 利用操作系統的層次化的文件結構將特定包的所有 .class 文件都置于同一個目錄下,而完整的文件路徑就是包名。為了盡可能讓我們的包名獨一無二,按照慣例,package 的第一部分是類的創建者的反順序的 Internet 域名,因為域名是獨一無二的。
剛開始接觸 Java 項目時很不習慣這一點,為什么一個包名搞這么復雜?讀到這里終于明白了……
二、訪問權限修飾詞
包訪問權限
沒有使用任何訪問權限修飾詞的成員,具有包訪問權限。即當前包中的所有其他類對該成員具有訪問權限,但是對于包外所有類,這個成員卻是 private。
public:接口訪問權限
public 修飾的成員所有類都可以訪問。
private:你無法訪問
除了包含該成員的類外,其他任何類都無法訪問。一般我們對外定義接口的時候,成員都是 private 權限,調用者想獲取成員值或者給成員賦值,需要使用接口對外提供的 public 方法:
public class BaseElement {
private string name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Java 還提供了 @Data 注解,可以省去我們手動寫這些 setName/getName 的方法,后面講注解的時候作者會講到。
private 還有一個常用的功能,就是可以控制如何構造一個對象,并阻止別人直接訪問某個構造器:
class Sundae {
private Sundae() {}
static Sundae makeASundae() {
return new Sundae();
}
}
當我們想構造一個 Sundae 對象時,不可以直接訪問默認構造器 Sundae(),只能通過類提供的靜態方法 makeASundae 構造,由于是靜態方法,所以只能構造一個 Sundae 對象,這就是我們實現單例的常用手段。
protected:繼承訪問權限
基類的創建者希望某個特定成員,把對它的訪問權限賦予派生類而不是所有類,就使用 protected。protected 也提供包訪問權限,即相同包內的其他類可以訪問 protected 元素。
三、類的訪問權限
上面主要講了四種訪問權限修飾詞,都是討論對類里的成員的作用,那么,它們對類本身的訪問權限是如何限制的呢?總結了一下,主要有以下幾點:
類既不可以是 private 的(這樣會使其他如何類都不可以訪問它 -- 只能自己玩,還有什么用?),也不可以是 protected 的(內部類除外,后面作者會講);
類的訪問權限只能是包訪問權限或者 public 的。