我們已經寫了一些Java程式。之前的每個Java程式都被儲存為一個文件,例如Test.java。隨後,程式被編譯為Test.class。我們最終使用$java Test來運行程式。
然而,在一個正常的Java專案中,我們往往需要寫不只一個.java程序,最終的Java產品包含了所有的Java程式。因此,Java需要解決組織Java程式的問題。套件(package)的目的就是為了更好的組織Java程式。
包的建立
包的建立非常簡單。我們只用在Java程式的開始加入package就可以了。我們以Human類別為例,將它放入包中:
複製代碼代碼如下:
package com.vamei.society;
public class Human
{
/**
* constructor
*/
public Human(int h)
{
this.height = h;
System.out.println("I'm born");
}
/**
* accessor
*/
public int getHeight()
{
return this.height;
}
/**
* mutator
*/
public void growHeight(int h)
{
this.height = this.height + h;
}
private int height;
}
上面的第一行語句複製程式碼程式碼如下:
package com.vamei.society;
表示該程式在com.vamei.society套件中。 com.vamei(vamei.com的反寫)表示包作者的網域(很可惜,這個網域已經被別人註冊了,所以只起示範作用)。 Java要求套件要有網域前綴,以便區分不同作者。 society為進一步的本地路徑名。 com.vamei.society共同構成了包包的名字。
套件為Java程式提供了一個命名空間(name space)。一個Java類別的完整路徑由它的套件和類別名稱共同構成,例如com.vamei.society.Human。對應的Human.java程式要放在com/vamei/society/下。類別是由完整的路徑識別的,所以不同的套件中可以有同名的類,Java不會混淆。例如com.vamei.society.Human和com.vamei.creature.Human是兩個不同的類別。
再看一個細節。 Human類別是public的,其建構方法也是public的,所以任意其他物件都可以呼叫該類別。我們之前說過,一個Java檔案中只能有一個public的類,該類別要去.java檔同名。一個類別可以沒有public關鍵字,它實際上也表示一種權限: 該類別在它所在的包中可見。也就是說,套件中的其他Java程式可以存取該類別。這是Java中的預設存取權限。
同樣,物件的成員也可以是預設權限(包中可見)。例如我們去掉getHeight()方法前面的public關鍵字。
包的調用
我們只要將Human.java編譯的Human.class放入對應的資料夾就可以了。例如,我將Human.class放入com/vamei/society/中。實際上,你也可以把.java檔放入對應路徑,Java會在使用時自動編譯。
如果整個套件(也就是com資料夾)位於目前的工作路徑中,那麼不需要特別的設置,就可以使用套件了,例如下面的TestAgain.java:
複製代碼代碼如下:
import com.vamei.society.*;
public class TestAgain
{
public static void main(String[] args)
{
Human aPerson = new Human(180);
System.out.println(aPerson.getHeight());
}
}
import用於識別路徑。利用import語句,我們可以引入對應路徑下的類別。 *表示引入society資料夾下的所有類別。在TestAgain中,我們直接使用了Human類。
我們也可以提供類別的完整的路徑。這可以區分同名但不同路徑的類,例如:
複製代碼代碼如下:
public class TestAgain
{
public static void main(String[] args)
{
com.vamei.society.Human aPerson =
new com.vamei.society.Human(180);
System.out.println(aPerson.getHeight());
}
}
由於我們提供了完整的類別路徑,所以不需要使用import語句。
如果套件沒有放在目前工作路徑下,我們在使用套件時,需要通知Java。例如,我們將套件放在/home/vamei/javapackage中,這樣Human.class位於/home/vamei/javapackage/com/vamei/society/Human.class,而我們的工作路徑為/home/vamei。這樣,包包就無法被找到。一個方法是使用javac和java時,用-classpath說明套件所在的資料夾路徑,例如:
複製代碼代碼如下:
$javac -classpath /home/vamei/javapackage:. TestAgain.java
$java -classpath /home/vamei/javapackage:. TestAgain
就是從/home/vamei/javapackage和工作路徑(.)中尋找套件。 Java可以從/home/vamei/javapackage可以找到Human類,從.可以找到TestAgain類別。
另外也可以設定係統的CLASSPATH環境變量,將上述路徑加入到該變數中,而不用每次都鍵入-classpath選項。
類似套件的機制在其他語言中也很常見,例如Python中的import機制。它們都是為了更好的組織和使用現有的程序。利用套件,我們可以比較容易的拓展Java程序,使用現有的Java程式庫。注意到,套件管理的是.class檔。 Java號稱"一次編譯,處處執行" (Compile Once, run anywhere)。 .class檔案可以在任意裝有Java虛擬機器(JVM, Java Virtual Machine)的平台上執行,這幫助我們克服了系統差異造成的程式移植困難。
系統之間的差異可以非常大。如果我們用C語言編寫程序,需要將原始程式在各個平台上重新編譯,以適應不同的硬體條件。 Java虛擬機銜接了平台和Java宇宙,它構成了硬體和程式邏輯的中間層。 JVM隱藏了硬體差異,提供給程式設計師一個「標準」的Java宇宙。而.class檔可以看做這個Java宇宙中流通的通貨。在JVM的基礎架構下,加上套件的管理輔助,Java程式實現了良好的可移植性(portability)。
總結
package, import
預設權限: 包中可見
-classpath, CLASSPATH