標籤:widget cte code 等級 大小寫 [] 隱藏 表示 目錄
在Java中,所有事物都具有某種形式的存取權限控制。
存取權限的控制等級從最大到最小依次為:public,protected,包存取權限(無關鍵詞)和private。
public,protected和private這幾個Java存取權限修飾詞在使用時,是置於類中每個成員(域或者方法)定義之前的。
一、類成員的存取權限
取得對某成員的訪問權的唯一途徑是:
1).使該成員成為public。無論誰在哪裡,都可以訪問該成員;
2).通過不加存取權限的修飾詞並將其他類放置於同一包內的方式給成員賦予包存取權限,包內的其他類可以訪問該成員;
3).繼承而來的類既可以訪問public成員也可以訪問protected成員。
4).提供訪問器和變異器方法,以讀取和改變數值。
1.包存取權限
預設存取權限沒有任何關鍵字,但通過是指包存取權限,這表示當前報中的所有其他類都對那個成員有存取權限,但是對於這個包之外的所有類,這個成員確是private。
包存取權限將包內所有相關的類組合起來,以使它們彼此之間可以輕鬆地相互作用。
注意:如果兩個類處於相同的目錄下,並且沒有給自己設定任何包名稱,Java會將這樣的檔案自動看作是隸屬於該目錄的預設包之中,於是這些檔案互相之間有包存取權限。
下面的例子說明了這個問題:
//類Cake和Pie處於同一目錄下,沒有明確的顯示在任何包中class Pie{ void f(){ System.out.println("Pie.f()"); }}class Cake{ public static void main(String[] args){ Pie x = new Pie(); x.f(); }}//輸出為Pie.f()
2.public:介面存取權限
使用關鍵字public,就意味著其後的成員聲明對所有人可用,特別是使用類庫的客戶程式員也是如此。
3.private:你無法訪問
關鍵字private表示出了包含該成員的類之外,其他任何類都無法訪問這個成員。同一包內的其他類不可以訪問這個類的private成員,因此這相當於自己隔離了自己。
private關鍵字的這種作用有許多用途,比如,控制如何建立對象,阻止別人直接存取某個特定的構造器(或全部構造器)。看下面的例子:
class Sundae{ private Sundae(){} static Sundae makeASundae(){ return new Sundae(); }}public class IceCream { public static void main(String[] args){ Sundae x = Sundae.makeASundae(); }}
這個例子裡,我們可以通過調用makeASundae()方法來建立Sundae對象,但是不能通過構造器來建立。
這對於類中的private域同樣適用。
但是要注意一點,不能因為在類中某個對象的引用是private,就認為其他的對象無法擁有該對象的public引用。
4.protected:繼承存取權限
如果建立了一個新包,並自另一個包繼承類,那麼唯一可以訪問的成員就是源包的public成員。
有時,基類的建立者希望將某個特定成員的存取權限賦予衍生類別而非所有類,這就需要使用關鍵字protected來實現。
注意,protected也提供包存取權限,即相同包內的其他類也可以訪問此類的protected元素。
二、介面和實現
存取權限的控制通常被稱為具體實現的隱藏。
把資料和方法封裝進類中,以及具體實現的隱藏,常共同被稱作是封裝。
出於兩個重要的原因,存取權限控制將許可權的邊界劃在了資料類型的內部:
1.要設定用戶端程式員可以使用和不可以使用的界限。可以在結構中建立自己的內部機制,兒不必擔心用戶端程式員會偶然地將內部機制當做是他們使用的介面的一部分。
2.介面和具體實現進行分離。
三、類的存取權限
Java中,存取權限修飾詞也可以用於確定庫中的哪些類對於該庫的使用者是可用的。
修飾詞必須放在關鍵字class之前。例如:
public class Widget{......}或improt access.Widget;
要知道,類不可以是private的(如果類是private的,那麼除了該類之外,其他任何類都不可以訪問它),也不可以是protected的(其實一個內部類可以是private或protected的,但這是特例,後續文章中敘述),只可以是包存取權限或public的。
如果不希望其他人訪問該類,可以把該類的所有構造器都指定為private,阻止任何人建立該類的對象。但這也有例外,這種做法不能阻止你在該類的static成員內部建立該類。我們來看下邊的例子:
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(){ //Soup1 soup = new Soup1; 不能執行 } void testSingleton(){ Soup2.access().f(); }}
我們可以看到,Soup1和Soup2類的構造器都是private的,誰也無法直接使用構造器來建立該類的對象了。但是我們也可以使用這兩個類:在Soup1中建立一個static方法,在這個方法中使用建構函式建立一個Soup1對象並返回它的引用;Soup2的建立用了設計模式中的單例模式,只能建立它的一個對象。Soup2類的對象是作為Soup2的一個static private成員而建立的,所以有且僅有一個,而且除非是通過public方法access(),否則是無法訪問到它的。
此外,一些限制也值得注意:
1.每個編譯單元都只能有一個public類。
2.public類的名稱必須完全與含有給編譯單元的檔案名稱相匹配,包括大小寫。
3.如果編譯單元內沒有帶public的類,這時可以對檔案隨意命名。
Java之路(五) 存取權限控制