1.使用C語言的程式員可能習慣於在沒有任何限制下訪問所有東東,這不是說不好,可能在個人英雄時代是非常好的,可是現在的軟體工程動不動就數十萬行代碼,早已不是單個程式員所能做的了,現在講的是TeamWork(團隊合作),為瞭解決多個程式員之間的命名和程式之間的溝通問題,C++提出了存取控制和命名空間的概念,存取控制也是物件導向中實現隱藏的主要手段.為什麼要隱藏?先談點,具體可以去研究物件導向的程式設計,“進行物件導向的設計時,一項基本的考慮是:如何將發生變化的東西與保持不變的東西分隔開。”
這一點對於庫來說是特別重要的。那個庫的使用者(客戶程式員)必須能依賴自己使用的那一部分,並知道一旦新版本的庫出台,自己不需要改寫代碼。而與此相反,庫的建立者必須能自由地進行修改與改進,同時保證客戶程式員代碼不會受到那些變動的影響。
為達到這個目的,需遵守一定的約定或規則。例如,庫程式員在修改庫內的一個類時,必須保證不刪除已有的方法,因為那樣做會造成客戶程式員代碼出現斷點。然而,相反的情況卻是令人痛苦的。對於一個資料成員,庫的建立者怎樣才能知道哪些資料成員已受到客戶程式員的訪問呢?若方法屬於某個類唯一的一部分,而且並不一定由客戶程式員直接使用,那麼這種痛苦的情況同樣是真實的。如果庫的建立者想刪除一種舊有的實施方案,共置入新代碼,此時又該怎麼辦呢?對那些成員進行的任何改動都可能中斷客戶程式員的代碼。所以庫建立者處在一個尷尬的境地,似乎根本動彈不得。
為解決這個問題,Java推出了“訪問指示符”的概念,允許庫建立者聲明哪些東西是客戶程式員可以使用的,哪些是不可使用的。這種存取控制的層級在“最大訪問”和“最小訪問”的範圍之間,分別包括:public,“友好的”(無關鍵字),protected以及private。根據前一段的描述,大家或許已總結出作為一名庫設計者,應將所有東西都儘可能保持為“private”(私人),並只展示出那些想讓客戶程式員使用的方法。這種思路是完全正確的,儘管它有點兒違背那些用其他語言(特別是C)編程的人的直覺,那些人習慣於在沒有任何限制的情況下訪問所有東西。到這一章結束時,大家應該可以深刻體會到Java存取控制的價值。 2.Java的存取控制和C++的不同之處針對類內每個成員的每個定義,Java訪問指示符poublic,protected以及private都置於它們的最前面——無論它們是一個資料成員,還是一個方法。每個訪問指示符都只控制著對那個特定定義的訪問。這與C++存在著顯著不同。在C++中,訪問指示符控制著它後面的所有定義,直到又一個訪問指示符加入為止 3."友好的"Java的類中如果沒有指明存取控制符,那麼預設的存取權限是當前的包,l也就是當前包的所有類可以訪問到這個“友好的”成員;(友好訪問使所有的類在一個包下好像有意義的組織了)package myjava.control;pubic class AccessControlDemo { public AccessControlDemo(){ System.out.println("This is AccessControlDemo"); } String getString() //友好的 { return "This is function getString"; } } AccessControlDemo.java必須駐留在名為control的一個子目錄內,而這個子目錄又必須位於由CLASSPATH指定的myjava目錄下面.不要錯誤地以為Java無論如何都會將目前的目錄作為搜尋的起點看待。如果不將一個“.”作為CLASSPATH的一部分使用,Java就不會考慮目前的目錄 4.public:介面訪問
使用public關鍵字時,它意味著緊隨在public後面的成員聲明適用於所有人,特別是適用於使用庫的客戶程式員 import myjava.control.*;
public class Demo{
public Demo() {
System.out.println("Demo constructor");
}
public static void main(String[] args) {
AccessControlDemo a=new AccessControlDemo // 建立AccessControlDemo對象 a.getString(); //此行出錯了,getString()只能被control包內的類訪問 }
} 5.預設包class Cake {
public static void main(String[] args) {
Pie x = new Pie();
x.f();
}
} 在位於相同目錄的第二個檔案裡:
//: Pie.java// The other classclass Pie { void f() { System.out.println("Pie.f()"); }}
最初可能會把它們看作完全不相干的檔案,然而Cake能建立一個Pie對象,並能調用它的f()方法!通常的想法會認為Pie和f()是“友好的”,所以不適用於Cake。它們確實是友好的——這部分結論非常正確。但它們之所以仍能在Cake.java中使用,是由於它們位於相同的目錄中,而且沒有明確的包名。Java把象這樣的檔案看作那個目錄“預設包”的一部分,所以它們對於目錄內的其他檔案來說是“友好”的
6.private(私人的)
private關鍵字意味著除非那個特定的類,
而且從那個類的方法裡,否則沒有人能訪問那個成員。同一個包內的其他成員不能訪問private成員,
這使其顯得似乎將類與我們自己都隔離起來。另一方面,也不能由幾個合作的人建立一個包。所以private允許我們自由地改變那個成員,同時毋需關心它是否會影響同一個包內的另一個類。
預設的“友好”包訪問通常已經是一種適當的隱藏方法;請記住,對於包的使用者來說,是不能訪問一個“友好”成員的。這種效果往往能令人滿意,因為預設訪問是我們通常採用的方法。對於希望變成public(公用)的成員,我們通常明確地指出,令其可由客戶程式員自由調用。
而且作為一個結果,最開始的時候通常會認為自己不必頻繁使用private關鍵字,因為完全可以在不用它的前提下發布自己的代碼(這與C++是個鮮明的對比)。然而,隨著學習的深入,
大家就會發現private仍然有非常重要的用途,特別是在涉及多執行緒的時候
private樣本程式
class Sundae { private Sundae() {} static Sundae makeASundae() { return new Sundae(); }}public class IceCream { public static void main(String[] args) { //! Sundae x = new Sundae(); Sundae x = Sundae.makeASundae(); }}
這個例子向我們證明了使用private的方便:有時可能想控制對象的建立方式,
並防止有人直接存取一個特定的構建器(或者所有構建器)。在上面的例子中,我們不可通過它的構建器建立一個Sundae對象;
相反,必須調用makeASundae()方法來實現.
此時還會產生另一個影響:由於預設構建器是唯一獲得定義的,而且它的屬性是private,所以可防止對這個類的繼承
7.protected(受保護的)
protected設定的存取控制主要用於對類的繼承中,等講到繼承的時候再說吧