1. 程式人生 > >Java基礎二 物件與類

Java基礎二 物件與類

1 類與物件

1 一個物件變數並沒有實際包含一個物件,而僅僅引用一個物件。在Java中,任何物件變數的值都是對儲存在另一個地方的一個物件的引用。new操作符的返回值也是一個引用。如果將一個方法應用於一個值為null的物件上,就會產生執行錯誤。區域性變數不會自動地初試化為null,而必須通過呼叫new或將它們設定為null進行初始化。可以將Java中的物件變數看作C++的物件指標。

2 在C++中,帶有const字尾的方法是訪問器方法;預設為更改器方法。但是在Java語言中,訪問器方法與更改器方法在語法上沒有明顯區別。

3 關鍵字public意味著任何類的任何方法都可以呼叫這些方法。關鍵字private確保只有類自身方法能夠訪問這些例項域,而其他類的方法不能夠讀寫這些域。

4 構造器與類同名,每一類可以有一個以上的構造器,構造器可以有0,1或多個引數,構造器沒有返回值,構造器總是伴隨著new一起使用。

5 在C++中,通常在類的外面定義方法,如果在類的內部定義方法,這個方法將自動地稱為內聯inline方法。在Java中,所有的方法都必須在類的內部定義,但並不表示它們是內聯方法。是否將某個方法設定為內聯方法是Java虛擬機器的任務。即時編譯器會呼叫那些簡潔,經常被呼叫,沒有被過載以及可優化的方法。

6 注意不要編寫返回引用可變物件的訪問器方法,因為如果返回了物件的引用就可以通過在外面的引用改變這個私有變數的狀態,從而破壞了封裝性。如果需要返回一個可變資料域的拷貝,就應該使用clone。

7 類的方法可以訪問類的任何一個物件的私有域,C++也有同樣的原則,方法可以訪問所屬類的私有特性,而不僅限於訪問隱式引數的私有特性。

8 有時可能希望將一個計算程式碼劃分為若干個獨立的輔助方法。通常這些輔助方法不應該成為公有介面的一部分,這是由於它們往往與當前的機制非常緊密,或者需要一個特別的協議以及一個特別的呼叫次序,最好將這樣的方法設計為private。

9 可以將例項域定義為final。構建物件時必須初始化這樣的域。也就是說,必須確保在每一個構造器執行之後,這個域的值被設定,並且在後面的操作中,不能夠再對它進行修改。例如,可以將Employee類中的name域宣告為final,因為在構建物件後,這個值不會再修改,即沒有setName方法。但是把物件引用定義為final,只是表示這個引用不會再指示其他物件,而不是這個物件不能修改。

2 靜態域和靜態方法

1 如果將域定義為static即靜態域,它屬於類,不屬於任何一個獨立的物件,為所有物件共享。

2 靜態常量即定義為static final,可以把它定義為public,因為final表明它不會被修改。譬如public static final double PI=3.1415926

3 靜態方法是一種不能向物件實施操作的方法,例如,Math類的pow方法就是一個靜態方法。在下面兩種情況使用靜態方法:a,一個方法不需要訪問物件狀態,其所需引數都是通過顯式引數提供的(例如Math.pow)。b一個方法只需訪問類的靜態域。

4 按值呼叫(call by name)表示方法接收的是呼叫者提供的值。而按引用呼叫(call by reference) 表示方法接收的是呼叫者提供的變數地址。一個方法可以修改傳遞引用所對應的變數值,而不能修改傳遞值呼叫所對應的變數值。Java總是採用按值呼叫。也就是說,方法得到的是所有引數值的一個拷貝。

5 方法引數共有兩種型別:基本資料型別(數字,布林值),物件引用。一個方法不可能修改一個基本資料型別的引數,但可以修改物件引用引用的物件。物件引用作為引數時,可以修改物件,因為引用拷貝後,依然引用的是物件,但是不能交換,因為交換的是引用的副本。

3 物件構造

1 如果多個方法有相同的名字,不同的引數,便產生了過載。Java允許過載任何方法,而不只是構造器方法。因此要完整地描述一個方法,需要指出方法名及引數型別。這叫做方法的簽名。返回型別不是方法簽名的一部分,也就是說,不能有兩個名字相同,引數型別也相同卻返回不同型別值的方法。

2 如果在構造器中沒有顯式地給域賦初值,那麼就會自動地被賦為預設值:數值為0,布林值為false,物件引用為null。

3 如果在編寫一個類時沒有編寫構造器,那麼系統就會提供一個無引數構造器,這個構造器將所有例項域設定為預設值。於是,例項域中的數值型資料設定為0,布林型資料設定為false,所有物件變數都將設定為null。如果類中提供了至少一個構造器,但是沒有提供無引數的構造器,則在構造物件時如果沒有提供引數就會被視為不合法。

4 在Java中可以在執行構造器之前,先執行賦值操作。當一個類的所有構造器都希望把相同的值賦予某個特定的例項域時,這種方式很有用。在C++中不能直接初始化類的例項域。

5 關鍵字this引用方法的隱式引數,而且這個關鍵字還有另一個含義,如果構造器的第一個語句形容this(...),這個構造器將呼叫同一類的另一個構造器。譬如:

public Employee(double s){
    //call Employee(String,double)
    this("Employee #"+nextId,s);
    nextId++;
}

採用這種方式使用this關鍵字非常有用,這樣對公共的構造器程式碼部分只編寫一次即可。在Java中,this引用等價於C++的this指標。但是在C++中,一個構造器不能呼叫另一個構造器,在C++中,必須將抽取的公共初始化程式碼編寫成一個獨立方法。

6 由於Java有自動的垃圾回收器,不需要人工回收記憶體,所以Java不支援析構器。

4 包

1 使用包的主要原因是確保類名的唯一性。標準的Java類庫分佈在多個包中,包括java.lang,java.util和java.net等。標準的Java包具有一個層次結構,如同硬碟的目錄巢狀一樣,可以使用巢狀層次組織包。從編譯器的角度看,巢狀的包之間沒有任何關係。例如java.util包與java.util.jar包毫無關係。每一個都擁有獨立的類集合。

2 當匯入的兩個包中的類名一樣時,需要在每個類名前加上完整的包名。

3 在C++中,與包機制類似的是名稱空間。在Java中,package與import語句類似於C++中的namespace和using指令。

4 標記為public的部分可以被任意的類使用;標記為private的部分只能被定義它們的類使用。如果沒有指定public或private,這個部分(類,方法或變數)可以被同一個包中的所有方法訪問。

5 類的設計技巧

1 要保證資料私有;一定要對資料初始化;不要在類中使用過多的基本型別;不是所有的域都需要獨立的域訪問器和域更改器;將職責過多的類進行分解;類名和方法名要能夠體現它們的職責;優先使用不可變的類。