華文網

30+的人學程式設計,使用預定義類(長文)

在Java中,沒有類就無法做任何事情,且並不是所有的類都具有物件導向的特徵,比如Math類。

1、物件與物件變數:

要想使用物件,就必須首先構造物件,並指定其初始狀態,然後,對物件應用方法;在Java中,

使用構造器構造新實例。構造器是一種特殊的方法,用來構造並初始化物件。

舉例說明:在Java類庫中有一個Date類,它的物件將描述一個時間點,比如:December 31,1999,23:59:59 GMT。

構造器的名字應該與類名相同,因此,Date類的構造器名為Date。要想構造一個Date物件,需要在構造器前面加上new操作符,如下所示:

new Date()

這個運算式構造了一個新物件,這個物件被初始化為當前的日期和時間。如果需要的話,也可以將這個物件傳遞給一個方法:

System.out.println(new Date());

或者,也可以將一個方法應用於剛剛創建的物件。如果希望構造的物件可以多次使用,我們需要將物件存放在一個變數中:

Date birthday = new Date();

創建一個新物件

在物件與物件變數之間存在著一個重要的區別,例如,語句:

Date deadline;

定義了一個物件變數deadline,它可以引用Date類型的物件,但是,一定要認識到,變數deadline不是一個物件,而且也沒有引用物件,這個時候,不能將任何Date方法應用於這個變數上,

我們必須首先初始化變數deadline,這裡有兩個選擇,可以用新構造的物件初始化這個變數:

deadline = new Date();

也可以讓這個變數引用一個已存在的物件;

deadline = birthday;

現在,這兩個變數引用同一個物件,如圖:

引用同一個物件的物件變數

一定要認識到:一個物件變數並沒有實際包含一個物件,而僅僅引用一個物件。

在Java中,任何物件變數的值都是對存儲在另外一個地方的一個物件的引用,new操作符的返回值也是一個引用。

2、Java類庫中的LocalDate類:

在前面的例子中,已經使用了Java標準類庫中的Date類。Date類的實例有一個狀態,即特定的時間點。

儘管在使用Date類時不必知道這一點,但時間是用距離一個固定時間點的毫秒數表示的,這個點就是所謂的紀元,它是UTC時間1970年1月1日00:00:00。

但是,Date類所提供的日期處理並沒有太大的用途,Java類庫的設計者認為:像Date這樣的日期只是西曆的固有習慣,像中國的農曆表示就很不一樣。

類庫的設計者決定將保存時間與給時間點命名進行分開,這樣,標準類庫分別包含了兩個類:一個是用來表示時間點的Date類,一個是用來表示大家熟悉的日曆標記法的LocalDate類。

將時間與日曆分開是一種很好的物件導向設計,通常最好使用不同的類表示不同的概念。

不要使用構造器來構造LocalDate類的物件,實際上,應當使用靜態工廠方法代表你調用構造器,下面的運算式:

LocalDate.now()

會構造一個新物件,表示構造這個物件時的日期。

可以提供年、月、日來構造對應一個特定日期的物件:

LocalDate.of(1999,12,31);

當然,通常都希望將構造的物件保存在一個物件變數中:

LocalDate newYearsEve = LocalDate.of(1999,12,31);

一時有了一個LocalDate物件,可以用方法getYear、getMonthValue、getDayOfMonth得到年月日:

int year = newYearsEve.getYear(); //1999

int month = newYearsEve.getMonthValue(); //12

int day = newYearsEve.getDayOfMonth(); //31

看起來,這樣寫代碼沒有什麼意義,因為這本來就是構造物件的那些值,不過關鍵的地方是,有時候那些日期或時間是通過計算得到的,所以才會有這種寫法。

3、更改器方法與訪問器方法:

再來看上一節中的plusDays方法調用:

LocalDate aThousandDaysLater = newYearsEve.plusDays(1000);

這個調用之後newYearsEve會有什麼變化?它會改為1000天之後的日期嗎?事實上,並沒有。plusDays方法會生成一個新的LocalDate物件,然後把這個新物件賦給aThousandDaysLater變數,原來的物件不做任何改動,我們說plusDays方法沒有更改調用這個方法的物件。

在Java的較早版本中有一個名為:GregorianCalendar的類來處理日曆,可以為這個類表示的日期增加1000天:

GregorianCalendar someDay = new GregorianCalendar(1999,11,31);

someDay.add(Calendar.DAY_OF_MONTH);

與LocalDate.plusDays方法不同,GregorianCalendar.add方法是一個更改器方法,調用這個方法後,someDay物件的狀態會改變,可以如下查看新狀態:

year = someDay.get(Calendar.YEAR); //2002

month = someDay.get(Calendar.MONTH) + 1; //09

day = someDay.get(Calendar.DAY_OF_MONTH); //26

正是因為這個原因,我們將變數命名為someDay而不是newYearsEve,調用這個更改器方法之後,它不再是新年前夜。

相反,只訪問物件而不修改物件的方法有時稱為訪問器方法。

我們來寫個日曆吧:格式如下圖:

日曆

詳細的代碼如下:

代碼

可以看到,利用LocalDate類可以編寫一個日曆程式,能處理星期幾以及各月天數不同等複雜問題,你並不需要知道LocalDate類如何計算月和星期幾,只需要使用這個類的介面和方法。

再來看上一節中的plusDays方法調用:

LocalDate aThousandDaysLater = newYearsEve.plusDays(1000);

這個調用之後newYearsEve會有什麼變化?它會改為1000天之後的日期嗎?事實上,並沒有。plusDays方法會生成一個新的LocalDate物件,然後把這個新物件賦給aThousandDaysLater變數,原來的物件不做任何改動,我們說plusDays方法沒有更改調用這個方法的物件。

在Java的較早版本中有一個名為:GregorianCalendar的類來處理日曆,可以為這個類表示的日期增加1000天:

GregorianCalendar someDay = new GregorianCalendar(1999,11,31);

someDay.add(Calendar.DAY_OF_MONTH);

與LocalDate.plusDays方法不同,GregorianCalendar.add方法是一個更改器方法,調用這個方法後,someDay物件的狀態會改變,可以如下查看新狀態:

year = someDay.get(Calendar.YEAR); //2002

month = someDay.get(Calendar.MONTH) + 1; //09

day = someDay.get(Calendar.DAY_OF_MONTH); //26

正是因為這個原因,我們將變數命名為someDay而不是newYearsEve,調用這個更改器方法之後,它不再是新年前夜。

相反,只訪問物件而不修改物件的方法有時稱為訪問器方法。

我們來寫個日曆吧:格式如下圖:

日曆

詳細的代碼如下:

代碼

可以看到,利用LocalDate類可以編寫一個日曆程式,能處理星期幾以及各月天數不同等複雜問題,你並不需要知道LocalDate類如何計算月和星期幾,只需要使用這個類的介面和方法。