From Gossip@caterpillar
Java Gossip: 套件(package)
隨著程式碼撰寫越來越多,程式內容越來越大,您會發現管理程式中的變數名稱、方法名稱、類別名稱也會是一件麻煩的事,尤其是一些同名問題的發生,例如在程式中,您也許會定義一個Point類別代表2維空間的點,也許在程式的某個地方,您也會定義一個 Point類別來表示一個3維空間的點,其它像函式同名、共用變數同名的情況也可能發生,當這種情況發生時,其中一個定義就可能將另一個定義給覆寫掉了。 Java提供package機制,它就像是一個管理容器,可以將您所定義的名稱區隔管理在package下,而不會有相互衝突的發生,例如您定義了一個 dimension2d與dimension3d的package,在它們之下都有一個Point類別,但由於屬於不同的package,所以這兩個名稱並不會有所衝突。 Java的package被設計為與檔案系統結構相對應,如果您的package設定是only.caterpillar,則該類別應該在指定目錄(或jar)的onlyfun/caterpillar下可以找到,為了要能建立與package相對應的檔案系統結構,您在編譯時可以加入-d 參數,並指定要建立在哪一個目錄之下。 下面這個程式使用"package"關鍵字來建立package以管理我們所定義的類別:
package onlyfun.caterpillar; 在編譯時要使用以下的指令: $ javac -d . UsePackage.java 在編譯時使用 "-d" 參數,並指定在現行目錄 "." 中建立檔案與系統結構,則編譯完成之後,在現行目錄中會出現onlyfun/caterpillar目錄,而當中有一個UsePackage.class 檔案,在編譯完成之後,package的指定就成為class名稱的一部份了,在執行時可以這麼下指令: $ java onlyfun.caterpillar.UsePackage Hello! World! 可以為類別建立package管理,舉下面的例子來說:
package onlyfun.caterpillar; 這個類別建立在Point2D.java檔案中,可以先用以下的指令來編譯它: $ javac -d . Point2D.java 之前說過,package名稱為類別名稱的一部份,除非您重新編譯類別,否則的話無法改變這個名稱,為了要使用這個類別,方法之一是使用完全描述(Fully qualified)名稱,也就是完整的指出package與類別名稱,例如:
public class UsePackage { 當然這個方法在使用上不是很方便,您可以使用"import"關鍵字,告知編譯器要使用的類別是位於哪一個package之下,如此可以少打一些字,讓編譯器多作一些事,例如:
import onlyfun.caterpillar.Point2D; 您在使用"import"時可以指定類別的完整描述,如果您會使用到某個package下的許多類別,您可以使用 '*',表示您可能使用到某個package下的某些類別,再讓編譯器作更多事,例如:
import onlyfun.caterpillar.*; 但要注意的是,如果您import之後,出現類別名稱有同名衝突時,編譯器就不知道如何處理了,例如: import java.util.Arrays; import onlyfun.caterpillar.Arrays; public class SomeClass { .... } 在這個例子中,編譯器發現有兩個Arrays類別,它不確定若遇到Arrays時您要使用的是java.util.Arrays,或是 onlyfun.caterpillar.Arrays,它只好回報以下訊息: java.util.Arrays is already defined in a single-type import import onlyfun.caterpillar.Arrays; ^ 1 error 這個時候您就要考慮換一下類別名稱了(如果您有權更動那些類別的話),或者是不使用"import",直接使用完整描述;在"import"時儘量不使用 '*' 也可以減少這種情況發生。 注意如果您提供的類別若不位於相同的package中,您的類別必須宣告為"public",若不宣告則類別預設只能於同一個package中被存取,例如將之前Point2D類別的public拿掉,則編譯UsePackage.java檔案時,會出現以下的錯誤: UsePackage.java:5: caterpillar.demo.Point2D is not public in caterpillar.demo; cannot be accessed from outside package 如果定義類別成員時沒有指定public、protected或private的存取修飾,則為預設(Default)權限,成員將只能於同一個package中被直接存取,通常稱之為package-friendly或package-private,且該成員將無法於子類別中被直接存取。 要存取package的class也與CLASSPATH的設定有關,建議您也看看官方網站上的文章,您對package的瞭解會更深入: Java平台的classes是被儲存在Java安裝目錄的jre/lib/下的rt.jar,另外額外的第三元件(Third- party)可以放在/jre/lib/ext/中,在之前的例子中,使用"import"就是在告知編譯器我們的類別位於哪一個package下,這些類別必須設定好CLASSPATH才可以被編譯器找到,預設上是jre/lib/下的rt.jar、jre/lib/ext/中相關擴充元件與現行工作目錄。 |
全站熱搜