命名空間及其作用

每個類裝載器有自己的命名空間,命名空間由所有以此裝載器為創始類裝載器的類組成。不同命名空間的兩個類是不可見的,但只要得到類所對應的Class對象的reference,還是可以訪問另一命名空間的類。

例2演示了一個命名空間的類如何使用另一命名空間的類。在例子中,LoaderSample2由系統類裝載器裝載,LoaderSample3由自定義的裝載器loader負責裝載,兩個類不在同一命名空間,但LoaderSample2得到了LoaderSample3所對應的Class對象的reference,所以它可以訪問LoaderSampl3中公共的成員(如age)。

例2不同命名空間的類的訪問

				/*LoaderSample2.java*/
import java.net.*;
import java.lang.reflect.*;
public class LoaderSample2 {
??? public static void main(String[] args) {
??????? try {
??????????? String path = System.getProperty("user.dir");
??????????? URL[] us = {new URL("file://" + path + "/sub/")};
??????????? ClassLoader loader = new URLClassLoader(us);
??????????? Class c = loader.loadClass("LoaderSample3");
??????????? Object o = c.newInstance();
??????????? Field f = c.getField("age");
??????????? int age = f.getInt(o);
??????????? System.out.println("age is " + age);
??????? } catch (Exception e) {
??????????? e.printStackTrace();
??????? }
??? }
				}
		
				/*sub/Loadersample3.java*/
public class LoaderSample3 {
??? static {
??????? System.out.println("LoaderSample3 loaded");
??? }
??? public int age = 30;
}

編譯:javac LoaderSample2.java; javac sub/LoaderSample3.java

運行:java LoaderSample2

LoaderSample3 loaded
age is 30

從運行結果中可以看出,在類LoaderSample2中可以創建處于另一命名空間的類LoaderSample3中的對象并可以訪問其公共成員age。

運行時包(runtime package)

由同一類裝載器定義裝載的屬于相同包的類組成了運行時包,決定兩個類是不是屬于同一個運行時包,不僅要看它們的包名是否相同,還要看的定義類裝載器是否相同。只有屬于同一運行時包的類才能互相訪問包可見的類和成員。這樣的限制避免了用戶自己的代碼冒充核心類庫的類訪問核心類庫包可見成員的情況。假設用戶自己定義了一個類java.lang.Yes,并用用戶自定義的類裝載器裝載,由于java.lang.Yes和核心類庫java.lang.*由不同的裝載器裝載,它們屬于不同的運行時包,所以java.lang.Yes不能訪問核心類庫java.lang中類的包可見的成員。

總結

在簡單討論了類裝載器,parent delegation模型,命名空間,運行時包后,相信大家已經對它們的作用有了一定的了解。命名空間并沒有完全禁止屬于不同空間的類的互相訪問,雙親委托模型加強了Java的安全,運行時包增加了對包可見成員的保護。