8-4 方法庫與套件包裝
方法:
8-4-1 Java 套件格式
VIDEO
對傳統語言的程式設計而言,一套完整的應用程式是由多個函數所構成。因此,我們可將某些特殊功能編寫成函數程式( Function),再編譯成『目的檔』( Object file),讓其他程式引用,如此可減少許多應用系統開發的時程,也可達到函數重複使用的目的。
一般會將所開發的函數集,依照功能歸類某些特定功能的群組,並可指定特定群組引用,因此稱之為『庫存函數』( Library ) 。一套系統開發工具(如 C 語言)的強弱,其關鍵在於所提供庫存函數的多寡。某些開發工具除了提供標準庫存函數之外,也會提供某些特殊功能的函數庫。譬如,某一套系統具有許多多媒體相關庫存函數,則稱之為『多媒體發展系統 』;如果具有許多工程繪圖庫存函數,則稱為『模具設計發展系統 』;如果具有許多動畫繪圖庫存函數,則稱為『 3 D
動畫發展系統 』 ...等等。
Java 也如同傳統語言一樣,可透過各種庫存函數,成為各式各樣的發展系統。更難得可貴的,大多數傳統語言的庫存函數都須購買,譬如具有視窗開發工具的 Visual 系列都必須付費購買。 Java 語言則不然,許多開發工具的套件都允許免費下載使用。當然,它也有需付費的企業版販售,但一般系統或初學者,基本版本就非常夠用。
圖 8-1 為 Java
套件結構 ,跟目錄結構一樣,是以樹狀結構排列。根目錄名稱為 java,每一端點代表一個套件名稱,端點以下可能另一個子套件端點,或該套件下的方法成員。但導入套件時,是以『點』( .)表示某一目錄,譬如
java.lang.Math 。
圖 8-6 Java 套件結構圖
自行製作套件( package)也是學習 Java
語言不可或缺的 。使用者可將常用的函數編製成套件,以供他人或爾後使用。引用自行定義的套件時,必須明確的告訴系統,套件所存放的位置,一般都利用 classpath 變數指明套件的目錄位置。當發展出許多套件之後,儲存於電腦上也必須佔用許多空間。 Java 發展出一套類似 Unix 系統上的 tar,將一大堆的檔案資料壓縮成較小的空間。 Java 發展出來的是 Java ARchive( jar 檔案)。可將 package 包裝於 jar 檔案內,如此可佔用比較小的空間,當被引用時,再展開回復原來的檔案型態。本章僅介紹套件產生方式,限於篇幅不再介紹其他處理。
8-4-2 套件編譯語法 - package VIDEO
( A )套件語法 - package
基本上,製作套件與類別 /物件方法非常相似。比較特殊的地方是,某些方法被包裝成套件後,大多不會限制使用者的身分如何,也都將其宣告成 public 屬性較為普遍,宣告 package 的語法如下:
套件宣告語法:
範例:
package package_name;
public class class_name {
public data_type variable_name;
…..
public return_type method_name{
….
}
…..
}
package dateTool;
public class Date {
public int year;
public int month;
public int day;
}
其中:
(1)
package :指定套件名稱關鍵字。譬如『 package dateTool;』則指定套件名稱為 dateTool。套建名稱存在的話,將所製作的類別檔案儲存於該名稱的目錄下;如果不存在,則新建立以套件名稱的目錄,再將類別檔案儲存該目錄底下。
(2)
public class class_name{ …} :宣告該套件下的類別。譬如『 public class Date { ..}』則建立一個 Date.class 類別,並儲存於 dateTool 目錄下。為了要讓其他檔案可以直接引用,必須宣告成 public 屬性。
(3)
public return_type method_name() { ..} :宣告該類別下的方法或物件成員。譬如『 public int year;』則宣告一個整數的變數成員;也必須宣告成 public 屬性。
( B )編譯套件 – javac -d
套件原始檔案製作完成之後,則可將其編譯成套件方法庫。編譯之前必須考慮套件的類別檔案儲存於何目錄下。基本上,在原始檔案內需指定套件名稱,編譯後類別檔案將儲存於該套件名稱的目錄下,但該套件名稱的目錄又在何處?除了編譯時必須指定儲存目錄外,也必須設定 classpath 環境變數,命令格式如下:
設定
classpath
環境變數:
範例:
> set classpath=path_name
> set classpath=G:\Examples\timeDate;.
編譯套件命令:
範例:
> javac –d path_name file_name
> javac –d G:\Examples\timeDate Date.java
上述範例中,設定 classpath 環境變數需特別注意,內容『 G:\Examples\timeDate;.』表示設定套件目錄( G:\Examples\timeDate)與目前目錄(『 .』)兩者。套件目錄如果不存在必須事先利用 Windows 命令建立,編譯後會將套件儲存於該目錄下。
( C )主程式導入 – import
當然自行開發的套件也可儲存於原 java 套件底下,但為了方便管理大多不會這樣;如果沒有儲存原 java 預定目錄下,欲導入運用又有稍微麻煩。欲導入自行開發的套件,也須利用 classpath 指名套件(如
set classpath=G:\Examples\timeDate;. )儲存目錄,導入語法如下:
套件導入語法:
範例:
import class_name;
……
public class main_class {
….
….
}
import dateTool.dateTool;
import dateTool.Date;
public class Ex8_3 {
…..
}
『 import class_name 』表示導入 class_name 類別。譬如『 import dateTool.Date 』表示導入 dateDate.Date 類別,但該類別必須儲存於 G:\Examples\timeDate 目錄下,然而 dateTool 也是目錄, Date.class 儲存於該目錄下。
8-4-3 範例研討:時間 / 日期工具套件
VIDEO
( A )程式功能: Ex8_3.java
請製作一套時間與日期計算工具的套件,再編寫一主程式導入該套件,並測試套件下類別方法與物件方法引用情形;期望操作結果如下:
G:\Examples\chap11\Ex8_3>javac Ex8_3.java
G:\Examples\chap11\Ex8_3>java Ex8_3
設定目前日期 ( 年 / 月 / 日 )
=>2007/8/25
設定目前時間 ( 時 / 分 / 秒 )
=>12/5/30
現在是
2007
年
8
月
25
日
12
時
5
分
30
秒
==
現在時刻輸出完畢
==
( B )製作技巧研討:
吾人可以稍加修改 Ex8_1 的時間計算工具( timeTool),以及 Ex8_2 的日期工具( dateTool),使其合乎套件語法再重新編譯即可。又 timeTool 類別是產生物件方法,而 dateTool 是類別方法,也剛好能滿足系統的要求。系統僅要求輸入字串格式輸入,轉換再輸出日期與時間格式,因此僅使用到 dateTool 類別中 getData() 方法,與 timeTool 類別中 getTime() 方法。
圖 8-7 timeDate 方法庫架構
吾人將
timeTool 物件方法( Ex8_1
範例) 與 dateTool 類別方法( Ex8_2
範例) ,整合成 timeDate 方法庫,如圖 8-6 所示。首先我們利用 classpath 環境變數指定方法庫儲存目錄位置( G:\Examples\timeDate),接下來再修改 Ex8_1 與 Ex8_2 的程式範例,各個程式說明如下:
( C )程式範例: Date.java
此程式原來是包含於 dateTool.java 檔案內,為了讓其他檔案可以直接引用,因此必須將它製作成獨立檔案,並宣告成 public 屬性。此程式經編譯後會產生 Date.class 類別,功能是產生儲存日期資料的物件,原始檔案如下:
01
02
03
04
05
06
07
08
09
10
11
// Date.java,
產生方法套件語法
//
儲存於
\Examples\timeDate
目錄下 ( 假設於
g
磁碟機 )
//
設定環境變數
> set classpath=g:\Examples\timeDate;.
//
編譯語法 :
> javac -d \Examples\timeDate Date.java
package
dateTool;
public class
Date {
public
int year;
public
int month;
public
int day;
}
(1) 第 1~4 行:說明使用。
( D )程式範例: Time.java
原來此程式式包含於 timeTool.java 內,我們將他分離成獨立程式。此程式將產生 Time.class 類別,功能是產生儲存時間資料的物件,程式範例如下:
01
02
03
04
05
06
07
08
09
// Time.java
package
timeTool;
/*
時間類別 ,
產生時間物件的格式
*/
public class
Time {
public
int hour;
public
int minute;
public
int second;
}
( E )程式範例: timeTool.java
吾人還是利用 Ex8_1 範例的 timrTool.java 範例(包含 4 個物件方法),將他複製到目前工作目錄下( chap8\Ex8_3),並稍加修改使成為套件的原始程式,修改地方以『粗黑』表示,顯示部分檔案如下:
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
// timeTool.java
//
儲存於
\Examples\timeDate
目錄下 ( 假設於
g
磁碟機 )
//
設定環境變數
> set classpath=g:\Examples\timeDate;.
//
編譯語法 :
> javac -d \Examples\timeDate timeTool.java
package
timeTool;
import java.util.*;
public
class timeTool {
/*
轉換字串成為時間物件格式
*/
public Time getTime(String time_S){
…..
…..
}
/*
之前時間計算器
*/
public Time timeBefore(Time now, Time value) {
…..
….
}
/*
之後時間計算器
*/
public Time timeAfter(Time now, Time value) {
…..
…..
}
/*
兩點時間之間距離計算器
*/
public Time timeInterval(Time start, Time end)
{
…..
…..
}
}
( F )程式範例: dateTool.java
將原來 dateTool.java( Ex8_2 範例,包含 4 個類別方法)稍加修改使成為套件的原始程式,修改地方以『粗黑』表示,顯示部分檔案如下:
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
// dateTool.java,
產生方法套件語法
//
儲存於
\Examples\timeDate
目錄下 ( 假設於
g
磁碟機 )
//
設定環境變數
> set classpath=G:\Examples\timeDate;.
//
編譯語法 :
> javac -d \Examples\timeDate dateTool.java
package
dateTool;
import java.util.*;
public
class dateTool {
/*
轉換字串成為日期物件格式
*/
public 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;
}
/*
之後天數的日期計算器
*/
public static Date dateAfter(Date now, int
value) {
….
….
}
/*
之前天數的日期計算器
*/
public static Date dateBefore(Date now, int
value) {
…..
…..
}
/*
計算兩個日期之間天數的計算器
*/
public static int dateInterval(Date start,
Date end) {
……
……
}
}
( G )程式範例: Ex8_3.java
吾人依照系統要求,製作一個簡單程式來測試引用套件內方法是否可以成功。圖 8-7 為 Ex8_3 類別內引用方法庫的運用情形,程式範例如下:
圖 8-8 Ex8_3 引用方法庫範例
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
// Ex8_3.java
//
庫存方法儲存於
G:\Examples\timeDate
目錄下 ( 假設於
G
磁碟機 )
//
設定環境變數
> set classpath=G:\Examples\timeDate;.
import dateTool.dateTool;
import dateTool.Date;
import timeTool.timeTool;
import timeTool.Time;
import java.io.*;
import java.util.*;
public class Ex8_3 {
public static void main(String args[]) throws
IOException {
BufferedReader keyin = new BufferedReader(new
InputStreamReader(System.in));
/*
時間工具是物件方法
*/
timeTool tool = new timeTool(); //
產生時間工具
Time now = new Time(); //
儲存目前時間
String time_S; //
讀入時間字串
/*
日期工具是類別方法
*/
Date today = new Date(); //
儲存今天日期
String date_S; //
讀入日期字串
/*
設定今天日期
*/
System.out.printf(" 設定目前日期 ( 年 / 月 / 日 )
=>");
date_S = keyin.readLine();
today = dateTool.getDate(date_S); //
引用類別方法
/*
設定目前時間
*/
System.out.printf(" 設定目前時間 ( 時 / 分 / 秒 )
=>");
time_S = keyin.readLine();
now = tool.getTime(time_S); //
引用物件方法
/*
輸出現在時刻
*/
System.out.printf("\n 現在是
%d
年
%d
月
%d
日 ",
today.year, today.month,
today.day);
System.out.printf(" %d
時
%d
分
%d
秒 \n",
now.hour, now.minute,
now.second);
System.out.printf("==
現在時刻輸出完畢
==\n");
}
}
( H )編譯原始程式
上述總共製作了 5 個原始檔案,其中 4 個檔案是套件程式,另一個是主程式,編譯如下:
G:\Examples\chap11\Ex8_3>javac -d \Examples\timeDate dateTool.java
G:\Examples\chap11\Ex8_3>javac -d \Examples\timeDate
timeTool.java
G:\Examples\chap11\Ex8_3>javac -d \Examples\timeDate
Time.java
G:\Examples\chap11\Ex8_3>javac -d \Examples\timeDate
Date.java
G:\Examples\chap11\Ex8_3>javac Ex8_3.java
G:\Examples\chap11\Ex8_3>dir/b
dateTool.java
timeTool.java
Ex8_3.java
Date.java
Time.java
Ex8_3.class
我們可以發現,編譯後僅多出來 Ex8_3.class 一個檔案,其他檔案將被放置於所指定的套件目錄下( G:\Examples\timeDate\),並且以套件名稱為目錄,儲存該套件下的類別檔案,可觀察如下:(可查閱到 4 個類別檔案儲存位置)
G:\Examples\chap11\Ex8_3>cd \Examples\timeDate
G:\Examples\timeDate>dir/b/s
G:\Examples\timeDate\dateTool
【 dateTool
目錄】
G:\Examples\timeDate\timeTool
【 timeTool
目錄】
G:\Examples\timeDate\dateTool\Date.class
【類別檔案】
G:\Examples\timeDate\dateTool\dateTool.class
【類別檔案】
G:\Examples\timeDate\timeTool\Time.class
【類別檔案】
G:\Examples\timeDate\timeTool\timeTool.class
【類別檔案】