最稳妥的路径是不加前导斜杠、直接写相对于 classpath 根的路径,如 "config/app.properties";加 "/" 会导致返回 null,资源须实际位于 classpath 中且需正确配置构建工具与 IDE。

ClassLoader.getResourceAsStream 读取资源时,路径写法直接影响能否成功获取流——关键不是“怎么写好看”,而是“怎么写才稳定不为空”。最稳妥的路径就是不加前导斜杠、直接写相对于 classpath 根的路径,比如 "config/app.properties" 或 "i18n/messages_zh_CN.properties"。
路径必须从 classpath 根开始,且不能带 "/"
ClassLoader 本身没有“当前包”概念,所有查找都默认从 classpath 根出发。加 "/" 不仅多余,还会导致返回 null:
- ✅ 正确:
getClassLoader().getResourceAsStream("logback.xml") - ❌ 错误:
getClassLoader().getResourceAsStream("/logback.xml")(多数 JDK 版本静默失败) - ⚠️ 注意:即使资源在
src/main/resources下,路径也直接写"logback.xml",不用补"src/main/resources/"前缀
资源必须实际落在 classpath 中
IDE 和构建工具(Maven/Gradle)需确保文件被复制到输出目录(如 target/classes 或 build/resources/main):
- Maven 项目中,把文件放在
src/main/resources下,它会自动进 classpath - IDE 中检查是否将资源目录标记为 “Resources Root”(IntelliJ)或 “Source Folder”(Eclipse)
- JAR 包里也能读:只要打包时资源进了 JAR 的根目录或对应子路径,
getResourceAsStream就能定位到
推荐搭配空值判断和 try-with-resources
资源可能缺失,流必须及时关闭。建议写法:
InputStream is = getClass().getClassLoader().getResourceAsStream("data.json");
if (is == null) {
throw new IllegalStateException("Resource 'data.json' not found in classpath");
}
try (InputStreamReader reader = new InputStreamReader(is, StandardCharsets.UTF_8);
BufferedReader br = new BufferedReader(reader)) {
String line;
while ((line = br.readLine()) != null) {
// 处理每一行
}
}
别和 Class.getResourceAsStream 混用路径逻辑
两者语义不同,混用容易出错:
-
Class.getResourceAsStream("a.txt")→ 查找位置是当前类所在包/a.txt -
Class.getResourceAsStream("/a.txt")→ 查找位置是classpath根/a.txt -
ClassLoader.getResourceAsStream("a.txt")→ 等价于上面第二种,但不接受 "/" 开头











