| |
8-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.java、dateTool.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 程式設計(二) 含物件導向
翻轉電子書系列:
|