Thinking in Java 讀書筆記 第六章 訪問權限控制

章六 訪問權限控制

前言

  本章的主要內容爲訪問控制,Java中共有四種訪問控制修飾符,訪問權限從大到小分別是publicprotected包訪問權限private。對於類成員,包括方法構造器以及後面即將介紹的內部類(內部接口),含上述所有四種訪問控制權限。對於類(接口)本身,只含有public包訪問權限這兩種訪問控制權限。
  訪問權限控制的初衷是分開類的接口實現。這樣一來,對於類的使用者(客戶端程序員)來說,只需瞭解類的接口即可使用類進行開發。二來,對類的設計者而言,可以在不改變類的接口的情況下,對類的實現進行重構,從而在後期提高類的性能。因此,訪問權限可以被視爲類創建者類使用者的協議。OOP的三大特徵,封裝繼承多態。其中封裝可以分爲兩層理解:第一層是將方法和數據封裝成,第二層是通過訪問控制隱藏具體實現。至於繼承和多態的內容,將在下面兩章詳解。
  初識訪問權限,一定要將對類本身的訪問權限和對類成員的訪問權限分開,不然會感到迷惑。Java設置訪問權限時,將訪問權限設置在了類內部,類成員的訪問權限是要理解的重點。對於類這一層而言,Java通過來組織內聚的類庫,對於包(類庫)內的每個.java文件,最多隻有一個public類且與文件名相同,文件中其他類不可加public修飾符,即爲包訪問權限,這些類被置於默認包中,包外不可見。

1. 包:庫單元

  內含一組類,它們在同一名字空間下被組織在一起,如Java SE中的工具包java.util,及其包中的成員類java.util.ArrayList。由此可見,包是Java中管理名字空間的機制,類似C++中的命名空間。Java中每一個.java文件被稱爲一個編譯單元,每個編譯單元只能有一個與文件名完全相同的public class類以及若干包訪問權限的類。

代碼組織

  編譯一個.java文件後,文件中的每個類都會生成.class的輸出文件。Java可運行程序是一組可以打包並壓縮爲Java文檔文件(JAR)的.class文件。Java解釋器負責這些文件的查找、裝載和解釋。包中的文件必須在文件中除註釋外的第一條程序代碼使用package語句,用以聲明該編譯單元出於該包內。其他包中必須通過import語句或指定全名來使用該類。

包名

  一個包中可以包括多個.class文件,爲避免混亂,可以將同一包中的所有.class文件置於同一目錄下。這樣可以解決兩個問題:命名查找。第一點,Java中通過反轉域名來對包進行命名,這樣可以保證包名的唯一性。第二點,Java把包名分解爲機器上的目錄,方便查找。
  若import兩個包中含有同名文件時,則需要給出全名以避免衝突。

定製工具庫

  此時,可以通過創建自己工具包來減少或消除重複代碼,如本書中作者使用的net.mindview的三個包,可以通過使用static import語句來直接使用類的static方法。

條件編譯

  Java沒有C的條件編譯功能。該功能主要用於跨平臺問題和調試。Java有JVM解決跨平臺問題。對於調試,Java可以通過修改import package語句在調試版開發版直接切換,實現調試功能。

使用包的忠告

  無論何時創建包,都已經在給定包的名稱的時候隱含指定了目錄結構。

2. Java訪問權限修飾符

  Java中,共有三個關鍵字用以修飾訪問權限:publicprotectedprivate;如果不加修飾,則爲默認訪問權限(包訪問權限);綜上,Java中共有4個不同的訪問權限。需要說明的是,Java訪問權限修飾符置於類的每個成員(域,方法,內部類)中,每個訪問權限修飾符控制其所修飾的特定成員的訪問權。下面,以訪問權限從小到大的順序介紹Java中4個不同的訪問權限。

private:無法訪問

  private修飾符表示,除了包含該成員的類之外,其他任何類都無法訪問該成員。通過隔離,類的設計者可以方便修改該成員。下面介紹private修飾符幾個常用的應用場景:

  • 控制對象創建:將類的一個或多個構造器設爲private,可以通過設立public方法調用private構造器來創建對象。
  • 助手方法:通過將助手方法設爲private,防止包內其他地方誤用,也方便自己修改。
  • :同C++一樣,除非必須公開底層細節,Java的域應該儘量設定爲private,可以設置access routines。

包訪問權限

  當類成員不加訪問修飾符時,則說明該成員爲包訪問權限。包訪問權限把類羣聚在一個包裏的做法提供了意義和理由。控制着那些代碼有權訪問自己的成員。要想取得對某成員的訪問權限的方法如下:

  • 使該成員成爲public,這樣,誰都可以訪問它。哪怕其類是默認訪問權限,也可通過繼承機制來訪問,程序示例如下:
class PackageOnly{
    public void accessible(){
        System.out.println("This method can be accessed anywhere, anyone");
    }
}
public class Public{
    //this public class inherits the method accessible 
    //now developers can get access to accessible through this class
}
  • 該成員爲protected,那麼該類的子類(不管在什麼地方)以及包內的其他類都可以訪問該成員
  • 該成員爲包訪問權限,將需要訪問的類與其放置在同一個包中,則包內的其他類可以訪問該成員
  • 該成員爲private,通過access routines訪問和修改該成員。

protected:繼承訪問權限

  protected訪問修飾符的訪問權限略大於包訪問權限,它將被修飾成員的訪問權限從同包擴展到了不同包的子類。對於包內的其他類,其訪問權限等同於包訪問權限。

public:接口訪問權限

  public被用來修飾能被隨意訪問的成員,也被稱爲類的接口。
  這裏需要補充的一點是,對於一個編譯單元中的非public類,其被視爲在包的默認包中,可以訪問其他類具有包訪問權限的成員。

3.類的接口與實現

   訪問權限的控制是對具體實現的隱藏,是OOP中封裝概念的一大支柱。Java將訪問控制權限用於修飾類成員,一方面設定了類使用者能使用和不能使用的界限;另一方面,將接口和具體實現分離。這樣,類的使用者可以通過閱讀API快速上手,而不必關係功能實現的細節。
  需要說明的是,javadoc所提供的註釋文檔的功能降低了程序代碼可讀性對客戶端程序員的重要性。可以採用一種以訪問權限從高到低的順序定義和實現類成員。

4.類的訪問權限

  類的訪問權限只有兩種:public包訪問權限。這裏,有一些注意事項:

  • 每個編譯單元(文件)都只能有一個public類。即每個編譯單元都有單一的公共接口,用public類表示。
  • public類的名稱必須完全與含有該編譯單元的文件名相匹配,包括大小寫。
  • 編譯單元內不帶public類也是可以的。但main()必須是public static的。

  除了顯示的public包訪問權限外,類還可以通過設置其所有構造器爲private來實現無法訪問的效果。這種情況下有一種例外,可以通過類的static成員創造該類實例。這樣,通過使用staticprivate可以實現一種常見的設計模式——單例模式,代碼示例如下:

class Singleton{
    private Singleton() {
        //do nothing here
    }
    private static Singleton single = new Singleton();
    public static Singleton getSingleton(){
        return single;
    }
}

  如上述代碼所示,通過設置類的構造器爲private,使得只能在類內static成員內創建該類示例。通過將single設置private,使得外部只能通過getSingleton()接口獲取single對象,實現了封裝。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章