ClassLoader.getSystemClassLoader().getResource(path)MyClass.class.getResource(path)(底層仍委派給載入該類的 ClassLoader)| 加載器 | 來源 | 負責載入 |
|---|---|---|
| Bootstrap Class Loader (根) | C++ 實作 | 核心類庫 JRE/lib/rt.jar |
| Extension Class Loader (擴展) | Java 實作 | 擴展目錄 JRE/lib/ext/*.jar |
| Application Class Loader (應用/系統) | Java 實作 | CLASSPATH 下所有類 |
三者為雙親委派模型(非繼承關係,而是組合關係),子加載器先委派父加載器載入,找不到再自行載入。
"com/example/config.properties"。
// 載入專案根類路徑下 demo/names.ser
URL url = ClassLoader.getSystemClassLoader().getResource("demo/names.ser");
public class Demo1 { ... }
// 1. 相對路徑:載入 Demo1 同包下的 names.ser
URL url1 = Demo1.class.getResource("names.ser");
// 2. 絕對路徑:載入類路徑根目錄下 demo/names.ser
URL url2 = Demo1.class.getResource("/demo/names.ser");
Class.getResource(String name) 內部流程:
resolveName(name) 轉換路徑。getClassLoader0())。ClassLoader.getSystemResource();否則呼叫 cl.getResource()。resolveName() 關鍵邏輯:
name.startsWith("/") → 去除首字元 '/',其餘作為相對類路徑根的路徑。故 Class.getResource() 本質上是對 ClassLoader.getResource() 的封裝,自動處理相對/絕對路徑轉換。
| 場景 | 正確寫法 | 錯誤示範 |
|---|---|---|
Maven 標準目錄 src/main/resources/config.yml | getResource("/config.yml") 或 getResource("config.yml")(同包) | getResource("resources/config.yml") |
| Spring Boot 專案 | 優先使用 ResourceLoader / @Value("classpath:...") / ClassPathResource | 硬編碼絕對檔案路徑 |
| 打包成 JAR 後讀取 | 僅能用 getResourceAsStream() 讀取流,不可用 File 操作 | new File(url.toURI()) 會在 JAR 內失敗 |
| 多模組專案共享資源 | 建立共用模組,資源放其 resources,依賴該模組即可透過類路徑載入 | 相對路徑 ../../module-x/src/main/resources |
ClassLoader 路徑永不以斜線開頭;
Class.getResource 相對當前包,絕對加斜線。
JAR 內唯有流可讀,File 物件不可用。
Spring 資源抽象最省心,標準規範少踩坑。