使用 package 管理類別


現在你所撰寫的類別,.java放在src資料夾中,編譯出來的.class放置在classes資料夾下,就檔案管理上比較好一些了,但還不是很好,就如同你會分不同資料夾來放置不同作用的檔案,類別也應該分門別類加以放置。


舉例來說,一個應用程式中會有多個類別彼此合作,也有可能由多個團隊共同分工,完成應用程式的某些功能塊,再組合在一起,如果你的應用程式是多個團隊共同合作,若不分門別類放置.class,那麼若A部門寫了個Util類別並編譯為Util.class,B部門寫了個Util類別並編譯為Util.class,當他們要將應用程式整合時,就會發生檔案覆蓋的問題,而如果現在要統一管理原始碼,也許原始碼也會發生彼此覆蓋問題。


你要有個分門別類管理類別的方式,無論是實體檔案上的分類管理,或是類別名稱上的分類管理,在Java語法中,有個package關鍵字,可以協助你達到這個目的。

請用編輯器開啟 編譯器與 SOURCEPATH 中Hello1/src資料夾中的Console.java,在開頭鍵入下圖開頭第一行文字:

將Console類別放在cc.openhome.util分類


這表示,Console類別將放在cc.openhome.util的分類下,以Java的術語來說,Console這個類別將放在cc.openhome.util套件(package)。
請再用文字編輯器開啟 編譯器與 SOURCEPATH 中Hello1/src資料夾中的Main.java,在開頭鍵入下圖開頭第一行的文字,這表示Console類別將放在cc.openhome的分類下:
將Main類別放在cc.openhome分類


套件的命名,通常會用組織或單位的網址命名,舉例來說,我的網址是opehome.cc,套件就會反過來命名為cc.openhome,由於組織或單位的網址是獨一無二的,這樣的命名方式,比較不會與其它組織或單位的套件名稱發生同名衝突。

當類別原始碼開始使用package進行分類時,就會具有四種管理上的意義:

  1. 原始碼檔案要放置在與package所定義名稱階層相同的資料夾階層
  2. package所定義名稱與class所定義名稱,會結合而成類別的完全吻合名稱(Fully qualified name)
  3. 位元碼檔案要放置在與package所定義名稱階層相同的資料夾階層
  4. 要在套件間可以直接使用的類別或方法(Method)必須宣告為public

關於第4點,牽涉到套件間的權限管理,將在之後介紹,這邊先不予討論,以下針對1到3點分別作說明。


原始碼檔案與套件管理

目前計劃將所有原始碼檔案放在src資料夾中管理,由於Console類別使用package定義在cc.openhome.util套件下,所以Console.java必須放在src資料夾中的cc/openhome/util資料夾,在沒有工具輔助下,你必須手動建立出資料夾,Main類別使用package定義在cc.openhome套件下,所以Main.java必須放在src資料夾中的cc/openhome資料夾。

這麼作的好處很明顯,日後若不同組織或單位的原始碼要放置在一起管理,就不容易發生原始碼檔案彼此覆蓋的問題。


完全吻合名稱(Fully qualified name)

由於Main類別是位於cc.openhome套件分類中,其完全吻合名稱是cc.openhome.Main,而Console類別是位於cc.openhome.util分類中,其完全吻合名稱為cc.openhome.util.Console

在原始碼中指定使用某個類別時,如果是相同套件中的類別,只要使用class所定義的名稱即可,而不同套件的類別,必須使用完全吻合名稱。由於MainConsole類別是位於不同的套件中,在Main類別中要使用Console類別,就必須使用cc.openhome.util.Console,也就是說,Main.java現在必須修改為:

package cc.openhome;

public class Main {
    public static void main(String[] args) {
        cc.openhome.util.Console.writeLine("Hello World");
    }
}

這麼作的好處在於,若另一個組織或單位也使用class定義了Console,但其套件定義為com.abc,則其完全吻合名稱為com.abc.Console,也就不會與你的cc.openhome.util.Console發生名稱衝突問題。


位元碼檔案與套件管理

目前計劃將所有位元碼檔案放在classes資料夾中管理,由於Console類別使用package定義在cc.openhome.util套件下,所以編譯出來的Console.class必須放在classes資料夾中的cc/openhome/util資料夾,Main類別使用package定義在cc.openhome套件下,所以Main.class必須放在classes資料夾中的cc/openhome資料夾。

你不用手動建立對應套件階層的資料夾,在編譯時若有使用-d指定位元碼的存放位置,就會自動建立出對應套件階層的資料夾,並將編譯出來的位元碼檔案放置至應有的位置。例如:

C:\workspace\Hello1>javac -sourcepath src -cp classes -d classes src/cc/openhome/Main.java

C:\workspace\Hello1>java -cp classes cc.openhome.Main
Hello World

C:\workspace\Hello1>

注意!由於Main類別位於cc.openhome套件中,所以上頭使用java執行程式時,必須指定完全吻合名稱,也就是指定cc.openhome.Main這個名稱。