在关于类加载方法之间的差异的流行答案中,Jon Skeet 指出,
类加载器资源路径始终被视为绝对路径。
一个更流行的答案用一个例子证实了这一说法。
将考虑所有路径 绝对路径。所以打电话ClassLoader.getResourceAsStream(path)
和String.getClassLoader().getResourceAsString("myfile.txt")
两者都会 在类路径中的以下位置查找文件:String.getClassLoader().getResourceAsString("/myfile.txt")
。./myfile.txt
忽略该示例无法编译的事实,共识表明前导斜杠与类加载器无关。
一个简单的测试表明情况并非如此。
Foo.class.getClassLoader().getResource("test.xml") // file
Foo.class.getClassLoader().getResource("/test.xml") // null
我只是将路径
files/test.xml
添加到测试项目的类路径中,其中一个名为 Foo
的类包含一个 main()
方法,打印出这两个调用的结果。既然数百人已经对上述答案进行了投票,我错过了什么?类加载器是绝对的还是依赖于输入名称的结构?
这篇Oracle 博客文章对我的理解很有帮助。
最终根据资源名称构造 URL 的方法是 URLClassPath.JarLoader.checkResource().
显然不是。
由类加载器来解释
name
中的 getResource(name)
。
检查
URLClassLoader
的源码,最终调用了
new URL(baseURL, name)
这里重要的是
name
是绝对的还是相对的
对于某些
baseURL
,绝对 /foo/bar
和相对 foo/bar
可能具有相同的效果。特别是,类路径中的“jar 文件 URL” 始终是这种情况
baseURL: jar:file:/home/duke/duke.jar!/
foo/bar -> jar:file:/home/duke/duke.jar!/foo/bar
/foo/bar -> jar:file:/home/duke/duke.jar!/foo/bar