JVM 需要類時,委派 ClassLoader 根據全限定名載入並返回 `Class` 物件。每個類持有對自己 ClassLoader 的引用。ClassLoader 負責載入所有資源:類、配置文件、圖片、網路位元組流等。
this.getClass().getClassLoader(); // 當前類的 ClassLoader
Thread.currentThread().getContextClassLoader(); // 當前線程上下文 ClassLoader
ClassLoader.getSystemClassLoader(); // 系統 ClassLoader(App ClassLoader)
注意:System ClassLoader ≠ Bootstrap ClassLoader(啟動類加載器,載入 rt.jar)。
// 1. Class.forName(靜態方法,觸發初始化)
Class cls = Class.forName("com.alexia.B");
B b = (B) cls.newInstance();
// 2. ClassLoader.loadClass(僅載入,不初始化)
ClassLoader cl = this.getClass().getClassLoader();
Class cls = cl.loadClass("com.alexia.B");
B b = (B) cls.newInstance();
// 3. 直接 new(最常用,但受包訪問限制)
B b = new B();
為何需要反射? 有包名的類無法直接 `new` 無包名類;`newInstance()` 要求類已載入並鏈接,`forName()` 完成此過程,提供解耦彈性。
File f = new File("C:/test/com/alexia/config/sys.properties"); // 絕對
File f = new File("com/alexia/config/sys.properties"); // 相對(相對工作目錄)
InputStream is = new FileInputStream(f);
InputStream is = this.getClass().getClassLoader()
.getResourceAsStream("com/alexia/config/sys.properties");
// 或 Thread.currentThread().getContextClassLoader()...
ResourceBundle bundle = ResourceBundle.getBundle("com.alexia.config.sys");
注意:`Properties.load()` 預設 ISO-8859-1 編碼,中文需轉碼。
目錄結構:
ContextRoot/
├── JSP/HTML/Image
└── WEB-INF/
├── web.xml
├── lib/
└── classes/ <-- 類與資源文件
| 資源類型 | 推薦方式 |
|---|---|
| 類 | 直接 new / Class.forName / ClassLoader |
| classpath 下文件 | ClassLoader.getResourceAsStream |
| properties 配置 | ResourceBundle / Properties.load |
| Web 靜態資源 | ServletContext.getResource |
出處:bianceng.cn