Java 程式設計()  第八章 方法與方法庫產生  上一頁    下一頁

 

8-3 類別方法

內容:

  • 8-3-1 類別方法宣告與引用

  • 8-3-2 範例研討:製作日期計算工具

  • 8-3-3 自我挑戰:預估葡萄成長採收日期

8-3-1 類別方法宣告與引用

類別可不經由 new 產生物件,類別內的方法成員可被直接引用,則稱為類別方法;宣告時只要在方法前面加入 static 關鍵字即可。某一類別程式呼叫其他類別方法時,兩類別實體(class 檔案)必須儲存於同一目錄下;宣告與引用語法如下:

宣告語法:

範例:

class class_name {

static return_type method_name() {

method_body;

}

…..

}

// 引用類別方法

class_name.method_name();

class mathFun {

static int  Add( intx, int y) {

…..

}

…..

}

// 引用類別方法

mathFun.Add();

如同一般類別的宣告語法,可以將類別宣告成私有性(private class)或公有性(public class),也可將方法成員宣告成私有性(private static)或公有性(public static

8-3-2 範例研討:製作日期計算工具

A)程式功能:Ex8_2.javadateTool.java

 許多系統都可能遇到日期計算問題,造成程式設計師困擾。因此,軟體公司裡期望建立相關日期計算工具,爾後所有工程師直接引用即可。該公司對日期計算規劃有下列工具:

(1) dataAfter()指定某一日期(年、月、日),再給予幾個天數之後的日期,應該是何日期。呼叫方法時,給予指定某一特定日期,與之後的天數。執行方法後回覆相對日期的年、月、日之日期。

(2) dataBefore()指定某一日期,再給予該日期之前的天數,則計算出相對應的日期。呼叫此方法時,給予指定特定日期(年、月、日),與之前的天數。執行後回覆相對應的年、月、日。

(3) dataInterval()指定兩個日期(年、月、日),則計算出兩日期之間的天數。呼叫此方法時,給予兩個日期,執行後回覆之間的天數。

期望操作及測試結果如下:

G:\Examples\chap11\EX8_2>java Ex8_2

設定目前日期(//) =>2004/3/12

 

目前是 2004 3 12

請輸入之前的天數 () =>100

之前是 2003 12 2

 

目前是 2003 12 2

請輸入之後的天數 () =>100

之後是 2004 3 12

 

目前是 2004 3 12

後面的第二個日期 (//) =>2005/4/6

兩點日期相差 390

B)製作技巧研討:

研發計算日前之前,需制定一個通用型的日期物件(Date),應包含有:年(year)、月(month)與(day)等三個變數成員。另外,每個月的天數並不相同,需要利用一個陣列(Months[])來表示每個月最高天數。還有一個重點,如欲利用數值的加減運算子,製作日期計算工具是非常困難的,採用計數累加方法,可能較為容易達成。製作技巧說明如下:

(1) 之後天數的日期(dateAfter():輸入第一點日期,與該日前之後的天數(value),計算並輸出第二點日期。製作方法是以第一點日期作基礎,由『日』(day)開始累計加一,當他超過該月最高天數(Months[])後,『月』(month)則累計加一,又如果『月』超過 12 時,則『年』累計加一;如此一個循環則輸入天數(value)減一,一直到該數值為 0。最後得到的日期即是第二點日期。

(2) 之前天數的日期(dateBefore():輸入第一點日期,與該日前之前的天數(value),計算並輸出第二點日期。方法是以第一點日期作基礎,由『日』開始累計減一,當它等於零,則『月』數累計減一,並將『日』設定為該月最高日數;如果『月』減一後等於 0,則『年』減一,亦將『月』設定為 12;如此一個循環則輸入天數(value)減一,依此類推,一直到輸入數值為 0

(3) 兩日期之間天數(dateInterval():與 dataAfter() 相似,由第一個日期開始累計,每次 value 數值累計加一。一直到第一個日期與第二個日期相同,最後 value 的數值即是兩日期之間的天數。

日期計算工具大多僅簡單的輸入與輸出運算,極少牽涉到共享資料的處理,製作成靜態類別方法即可。因此我們將宣告日期物件(Date)與日期工具(dateTool())兩類別規劃於 dateTool.java 檔案內,編譯後(javac)將產生 Data.class dateTool.class 兩類別檔案,其中 dateTool.class 包含三個類別方法。另一方面,也製作了一個主程式(Ex8_2.java)測試這三個類別方法是否正確。

C)程式範例:dateTool.java

吾人利用 dateTool.java 檔案規劃 Date dateTool 兩類別。Date 類別可宣告產生儲存日期的物件(年、月、日)。dateTool 類別包含 4 個靜態方法成員與 1 個變數成員,分別說明如下:(如圖 8-4 所示)

(a) Date 類別:規劃日期物件的儲存格式,包含年(year)、月(month)與日(day)等變數成員。

(b) Month[] 類別變數:儲存每年 12 個月,每月的日數(12 個元素)。

(c) getDate() 方法:將日期字串(年//日)轉換成日期物件格式(年、月、日)。

(d) dateBefore() 方法:計算某一指定日期,相對應之前的天數量,應該是何日前(年、月、日)。

(e) dateAfere() 方法:計算某一指定日期,相對應之後的天數量,應該是何日前(年、月、日)。

(f) dateInterval():計算兩日期之間的天數量。

8-4 Date dateTool 類別的功能

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

//dateTool.java

 

import java.util.*;

 

/* 日期類別, 產生日期物件的格式 */

class Date {            

     int year;

     int month;

     int day;

}

 

/* 時間工具類別, 包含 4 個方法 (計算器) */

class dateTool {

    /* 每月的天數 */

    static int Months[] = {31, 28, 31, 30, 31, 30,

                     31, 31, 30, 31, 30, 31};

 

    /* 轉換字串成為日期物件格式 */

    static Date getDate(String date_S){

        Date date = new Date();

        Scanner s = new Scanner(date_S).useDelimiter(“/”);

        date.year = s.nextInt();

        date.month = s.nextInt();

        date.day = s.nextInt();

        return date;

    }

 

    /* 之後天數的日期計算器 */

    static Date dateAfter(Date now, int value) {

        int k;

        while(value >0) {

           now.day = now.day + 1;

           if(now.day > Months[now.month-1]) {

                 now.day = 1;

                 now.month = now.month + 1;

                 if (now.month > 12) {

                     now.month = 1;

                     now.year = now.year + 1;

                 }

           }

           value = value – 1;

        }

        return now;

    }

             

    /* 之前天數的日期計算器 */

    static Date dateBefore(Date now, int value) {

        while(value > 0) {

            now.day = now.day – 1;

            if (now.day < 1) {

                now.month = now.month – 1;

                if (now.month < 1) {

                    now.month = 12;

                    now.year = now.year –1;

                }

                now.day = Months[now.month-1];

            }

            value = value – 1;

        }

        return now;

    }    

 

    /* 計算兩個日期之間天數的計算器 */

    static int dateInterval(Date start, Date end) {

        int number=0;

        while(!((end.year == start.year)&&

                (end.month == start.month)&&

                (end.day == start.day))) {

             start.day = start.day +1;

             if (start.day > Months[start.month-1]) {

                   start.month = start.month + 1;

                   start.day = 1;

                   if (start.month >12) {

                       start.year = start.year +1;

                       start.month = 1;

                   }

             }

             number = number + 1;

        }

        return number;

    }

}

程式重點說明:

(1) 6~10 :『class Date { …}』。宣告日期類別。產生日期物件的格式。

(2) 13~84 :『class dateTool { …}』。宣告日期工具類別。

(3) 15~16 :『static int Months[] = { …}』。每月最高日期陣列。

D)程式範例:Ex8_2.java

完成時間計算工具製作之後,吾人編寫 Ex8_2.java 程式來驗證工具是否運作正常。又 dateTool 工具內的方法皆被宣告成靜態方法,可不經由產生物件,即可直接引用執行,如圖 8-4 所示。

8- 5 Date 物件產生與 dateTool 的類別方法

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

//Ex8_2.java

 

/* dateTool.class, Date.class 需儲存於相同目錄下 */

import java.io.*;

import java.util.*;

public class Ex8_2 {

    public static void main(String args[]) throws IOException {

         BufferedReader keyin = new BufferedReader(new

                                    InputStreamReader(System.in));

 

         Date now = new Date();            // 儲存當時日期

         Date date_T = new Date();         // 日期暫存變數

         Date date_B = new Date();         // 日期暫存變數

         String date_S;                    // 讀入日期字串

         int value;

 

         /* 設定目前日期 */

         System.out.printf("設定目前日期(//) =>");

         date_S = keyin.readLine();

         now = dateTool.getDate(date_S);

 

         /* 測試某日前之前天數的日期 */

         System.out.printf("\n目前是 %d %d %d \n",

                                  now.year, now.month, now.day);

         System.out.printf("請輸入之前的天數 () =>");

         value = Integer.parseInt(keyin.readLine());

         date_B = dateTool.dateBefore(now, value);

         System.out.printf("之前是 %d %d %d \n",

                            date_B.year, date_B.month, date_B.day);

 

         /* 測試某日前之後天數的日期 */

         System.out.printf("\n目前是 %d %d %d \n",

                                  now.year, now.month, now.day);

         System.out.printf("請輸入之後的天數 () =>");

         value = Integer.parseInt(keyin.readLine());

         date_B = dateTool.dateAfter(now, value);

         System.out.printf("之後是 %d %d %d \n",

                            date_B.year, date_B.month, date_B.day);

 

         /* 測試計算兩日前之間的天數 */

         System.out.printf("\n目前是 %d %d %d \n",

                                  now.year, now.month, now.day);

         System.out.printf("後面的第二個日期 (//) =>");

         date_S = keyin.readLine();

         date_T = dateTool.getDate(date_S);

         value = dateTool.dateInterval(now, date_T);

         System.out.printf("兩點日期相差 %d \n", value);

     }

}

8-3-3 自我挑戰:預估葡萄成長採收日期

A)程式功能:PM8_2.java

南投縣信義鄉種植葡萄的生長情況大致上是這樣,葡萄收成後農夫會將所有綠葉剪光,此時讓葡萄樹休養,等到希望葡萄開始成長時,再將成長激素擦拭於藤枝的某些地方,新芽將由擦拭藥水的地方開始成長。由擦拭成長激素日開始計算,其他工作週期如下:

(a) 7 後會發新芽。

(b) 30 後會長出花苞;

(c) 之後每隔 10 必須噴農藥一次,連續 5

(d) 同時,每隔 20 必須下普通有機肥料一次,連續 3 ;離最後加肥 40 ,必須加高蛋白有機肥料一次

(e) 最後噴農藥後, 20 需葡萄果實需套裝紙袋。

(f) 從擦拭成長激素到收割葡萄,大約需要 200

農民除了需要依照整個成長過程施肥與噴灑農藥外,也需時常觀察葡萄藤與樹葉的變化,是否『落菌』感染,如發現有被感染必須立即再噴灑消除藥水,絕對不可延遲到隔日,否則就前功盡棄。種植葡萄並不容易,整個成長過程中有稍微瑕疵的話,輕者品質不良,收成當然不好;重者整片葡萄園全部作廢,血本無歸。當然農民也希望辛苦可以得到代價,葡萄可以賣到好價錢。但葡萄要賣到好價錢,除了需要細心照顧外,也要仰賴上天不要有天然災害(雨水過量、寒流、下冰砲、颱風...等),更重要的是採收日期是否剛好合時,譬如:採收當時其他水果產量不豐,或葡萄成長時期天然災害少果實賣像好,就更容易賣到好價錢。由此可見,選定何時可以採收葡萄是很重要的。掌握了這些因素之外,信義鄉梁姓與黃姓兩位年輕農民,便組織了一個葡萄產銷班,期望班友之間採收期錯開。因此,建立一個教導同班農民種植葡萄的教學網站,農民只要輸入預期何時採收葡萄,系統會告知何時擦拭成長激素的,也會一序列告知農民需要從事哪些工作的日期,也隨時提醒農民應該預備哪些工作。所有班友依照此系統種植葡萄,如成長過程與系統不符,則可能種植過程有瑕疵,或系統評估不正確。因此該產銷班必須定期開會,農民將種植心得提出意見,再來修飾系統。請您幫他們製作一個雛型系統,期望操作介面如下:(數據並非確實,僅作教學參考)

G:\Examples\chap11\PM8_2>java PM8_2

== 信義鄉葡萄第 # 產銷班 種植施工預估系統 ==

=>本系統評估成長及種植過程僅供農友參考 <=

=>系統有不妥或有新種植技術請與班長聯繫 <=

請輸入預定採收日期 (國曆 //) =>2008/9/15

 

預計採收日期 2008 9 15 日種植工程序列如下:

 

預估自擦拭成長激素後 200 天可採收

擦拭日期是 2008 2 27

 

發芽日期是 2008 3 6

 

開花日期是 2008 4 5

 

== 開花後噴灑農藥日期 ==

1 次是 2008 4 15

2 次是 2008 4 30

3 次是 2008 5 15

4 次是 2008 6 4

5 次是 2008 6 24

 

== 發芽後施放有機肥料日期 ==

1 次是 2008 4 10

2 次是 2008 4 30

3 次是 2008 5 20

最後一次是高蛋白有機肥料, 請到班長處索取配方

 

套裝紙袋日期是 2008 5 25

== 列印完畢 歡迎再度使用 ==

B)製作技巧提示:

引用 Ex8_2 範例的日期工具(dateTool),製作本系統就非常簡單了,只要將 dataTool.java 檔案複製到目前目錄下,再重新編譯即可。除了日期工具外,吾人以虛擬碼提示部份程式要點,如下:

/* dateTool.class, Date.class 需儲存於相同目錄下 */

         /* 預估相關成長與施工週期 */

         final int totalDays = 200;               // 所需成長時間 ()

         final int bornLeaf = 7;                 // 發芽時間

         final int bornFlower= 30;               // 開出花苞時間

         final int dust[] = {10, 15, 15, 20, 20};     // 花苞後噴灑農藥週期

         final int organic[] = {5, 20, 20};         // 發芽後有機肥料週期

         final int bagging = 50;                 // 開出發苞後需套裝紙袋天數

         /* 宣告所需物件與變數 */

         Date cropDate = new Date();           // 收成日期

         Date startDate = new Date();          // 擦拭成長激素日期

         Date leafDate = new Date();           // 發芽日期

         Date bornDate = new Date();           // 開出花苞日期

         Date tempDate = new Date();           // 日期暫存器

         String date_S;                        // 讀入日期字串

         int value;

         ………

         System.out.printf("請輸入預定採收日期 (國曆 //) =>");

         date_S = keyin.readLine();

         cropDate = dateTool.getDate(date_S);     // 類別方法引用

         列印預計採收日期;

         /* 計算擦拭成長激素日期 */

         startDate = dateTool.dateBefore(cropDate, totalDays);  // 類別方法引用

         列印擦拭成長激素日期;

         /* 計算發芽日期 */

         leafDate = dateTool.dateAfter(startDate, bornLeaf);    // 類別方法引用

         列印發芽日期;

         /* 計算開花日期 */

         bornDate = dateTool.dateAfter(startDate, bornFlower);  // 類別方法引用

         列印開花日期;

        /* 計算噴灑農藥日期 */

        tempDate.year = bornDate.year;

        tempDate.month = bornDate.month;

        tempDate.day = bornDate.day;

        for(int i=0; i<dust.length; i++) {

            tempDate = dateTool.dateAfter(tempDate, dust[i]);  // 類別方法引用

            列印噴灑農藥日期;

        }

          …….

……..

 

翻轉工作室:粘添壽

 

Java 程式設計(二) 含物件導向

 

 

翻轉電子書系列: