1. 程式人生 > >第4章 物件與類

第4章 物件與類

1.在物件與物件變數之間存在著一個重要的區別。
例如 , 語句
Date deadline ; / / deadline doesn ' t refer to any object
定義了一個物件變數 deadline , 它 可 以 引 用 Date 型別的物件。
但是 , 一定要認識到 :
變數deadline 不是一個物件 , 實際上也沒有引用物件。
此時 , 不能將任何Date 方法應用於這個變數上。
語句
s = deadline . toStringO ; / / not yet
將產生編譯錯誤。
必須首先初始化變數 deadline , 這裡有兩個選擇。
當然 , 可以用新構造的物件初始化這個變數 :
deadline = new Date ( ) ;


也讓這個變數引用一個已存在的物件 :
deadline = birthday ;

2、java 日期類LocalDays之後深入研究。

3、在這個示例程式中包含兩個類 : Employee 類和帶有 public 訪問修飾符EmployeeTest
類。 EmployeeTest 類包含了main 方法, 其中使用了前面介紹的指令 。原始檔名是EmployeeTest . java, 這是因為檔名必須與 public 類的名字相匹配 。 在一個
原始檔中,只能有一個公有類, 但可以有任意數目的非公有類 。
接下來, 當編譯這段原始碼的時候 ,
編譯器將在目錄下建立兩個類檔案 :
EmployeeTest .class 和 Employee . class
將程式中包含 main 方法的類名提供給位元組碼直譯器 , 以便啟動這個程式 :
java EmployeeTest
位元組碼直譯器開始執行 EmployeeTest 類的 main 方法中的程式碼 。 在這段程式碼中 , 先後構
造了三個新 Employee 物件 , 並顯示它們的狀態 。

4.構造器與其他的方法有一個重要的不同。 構造器總是伴隨著new 操作符的執行被呼叫
,而不能對一個已經存在的物件呼叫構造器來達到重新設定例項域的目的。

5、C + + 註釋:
Java 構造器的工作方式與 C + + — 樣 。 但是 , 要記住所有的 Java 物件都是在 Java 構造器的工作方式與 C + + — 樣 。 但是 , 要記住所有的 Java 物件都是在堆中構造的 , 構造器總是伴隨著 new 操作符一起使用 。 C + + 程式設計師最易犯的錯誤就是忘記 new 操作符 :

Employee number 007 ( " ] anie 5 Bond " , 100000 , 1950 , 1 , 1 ) ;// C + + , not Java

這條語句在 C + + 中能夠正常執行, 但在Java 中卻不行。

6、警告 : 請注意 , 不要在構造器中定義與例項域重名的區域性變數
。 例如 , 下面的構造器將無法設定 salary。
public Employee ( St ring n , double s , . .
{
String name = n ; / / Error
double salary = s ; / / Error
}
這個構造器聲明瞭區域性變數 name 和 salary。 這些變數只能在構造器內部訪問 。 這些變數遮蔽了同名的例項域有些程式設計者常常不假思索地寫出這類程式碼,因為他們已經習慣增加這類資料型別 。 這種錯誤很難被檢查出來, 因此 ,必須注意在所有的方法中不要命名與例項域同名的變數 。

7、警告 : 注意不要編寫返回引用可變物件的訪問器方法 。 在 Employee 類中就違反了這個設
計原則 , 其中的 getHireDay 方法返回了一個 Date 類物件 :

class Employee
{
private Date hireDay ;
public Date getHireDayO
{
return hireDay ; / / Bad

LocalDate 類沒有更改器方法 , 與之不同 , Date 類有一個更改器方法 setTime , 可以
在這裡設定毫秒數。Date 物件是可變的 , 這一點就破壞了封裝性 !

8、一個方法可以訪問所屬類的所有物件的私有資料, 這令很多人感到奇怪! 例如, 下面看一下用來比較兩個僱員的 equals 方法 。
class Employee
{
public boolean equals ( Employee other )
{
return name . equals ( other . name ) ;
}
}
典型的呼叫方式是
if ( harry , equals ( boss ) ) . . .
這個方法訪問 harry 的私有域 , 這點並不會讓人奇怪, 然而 , 它還訪問了
boss 的私有域。 這是合法的 , 其原因是 boss 是 Employee 類物件 , 而 Employee 類的方法可以訪問 Employee 類的任何一個物件的私有域。

9、final 修飾符大都應用於基本 ( primitive ) 型別域, 或不可變 ( immutable )類的域 ( 如果類中的每個方法都不會改變其物件 , 這種類就是不可變的類。 例如 , String 類就是一個不可變的類 ) 。對於可變的類,使用 final 修飾符可能會對讀者造成混亂。
例如 ,
private final StringBuiIcier evaluations ;
在 Employee 構造器中會初始化為
evaluations = new StringBuilder ( ) ;
final 關鍵字只是表示儲存在 evaluations 變數中的物件引用不會再指示其他 StringBuilder
物件 。 不過這個物件可以更改 :

public void giveGoldStarO
{
evaluations . append ( LocalDate . now ( ) + " : Gold star ! \ n " ) ;
}

10、靜態方法是一種不能向物件實施操作的方法。可以認為靜態方法是沒有this引數(隱式引數)的方法,靜態方法因此不能訪問自身類的例項域,但是靜態方法可以訪問自身類中的靜態域。非靜態方法可以訪問自身類的靜態域嗎?答案是當然的,非靜態方法可以訪問自身類的所有域。

11、直接通過類名或者類物件例項都可以呼叫靜態方法,但是因為靜態方法與類物件例項本身往往沒有關係,所以通常建議用類名,而不是物件類呼叫靜態方法。

12、提示 : 每一個類可以有一個 main 方法。 這是一個常用於對類進行單元測試的技巧 。 例如,可以在 Employee 類中新增一個 main 方法 。如果想要獨立地測試 Employee 類 , 只需要執行
java Employee
如果 Employee 類是一個更大型應用程式的一部分,就可以使用下面這條語句執行程式
java Application
Employee 類的 main 方法永遠不會執行 。

13、很多程式設計語言 ( 特別是 , C ++ 和 Pascal ) 提供了兩種引數傳遞的方式 : 值呼叫和引用呼叫。 有些程式設計師 ( 甚至本書的作者 ) 認為 Java程式設計語言對物件採用的是引用呼叫,實際上 , 這種理解是不對的 。 由於這種誤解具有一定的普遍性 , 所以下面給出一個反例來詳細地闡述一下這個問題。首先, 編寫一個交換兩個僱員物件的方法 :
public static void swap ( Employee x , Employee y ) / / doesn ’ t work
Employee temp = x ;
x = y ;
y = temp ;
}
如果 Java 對物件採用的是按引用呼叫, 那麼這個方法就應該能夠實現交換資料的效果 :
Employee a = new Employee ( " Alice " , . . . ) ;
Employee b = new Employee ( " Bob " , . . . ) ;
swap ( a , b ) ;/ / does a now refer to Bob , b to Alice ?
但是, 方法並沒有改變儲存在變數 a 和 b 中的物件引用 。 swap 方法的引數 x和 y 被初始
化為兩個物件引用的拷貝, 這個方法交換的是這兩個拷貝 。
/ / x refers to Alice , y to Bob
Employee temp = x ;
x = y ;
y = temp ;
/ / now x refers to Bob , y to Alice
最終, 白費力氣 。 在方法結束時引數變數X 和 y 被丟棄了 。 原來的變數 a 和 b 仍然引用這個方法呼叫之前所引用的物件。這個過程說明 : Java 程式設計語言對物件採用的不是引用呼叫, 實際上 , 物件引用是按值傳遞的 。

14、包、類路徑、註釋部分之後再研究。