Class.getResource() 和 ClassLoader.getResource() 之间有什么区别?

2022-08-31 05:54:22

我想知道 和 之间有什么区别?Class.getResource()ClassLoader.getResource()

编辑:我特别想知道文件/目录级别是否涉及任何缓存。如“目录列表是否缓存在类版本中?

AFAIK以下基本上应该做同样的事情,但它们不是:

getClass().getResource() 
getClass().getClassLoader().getResource()

我在处理一些报告生成代码时发现了这一点,这些代码从该目录中的现有文件创建新文件。使用 Class 中的方法时,我可以使用 找到部署时存在的文件,但是当尝试获取新创建的文件时,我收到了一个 null 对象。浏览目录清楚地表明新文件在那里。文件名前面有一个正斜杠,如“/myFile.txt”。WEB-INF/classes/getClass().getResource()

另一方面,的版本确实找到了生成的文件。从这种经验来看,似乎正在对目录列表进行某种缓存。我说得对吗,如果是这样,这在哪里记录?ClassLoadergetResource()

API 文档Class.getResource()

查找具有给定名称的资源。用于搜索与给定类关联的资源的规则由该类的定义类装入器实现。此方法委托给此对象的类装入器。如果此对象是由引导类装入器装入的,则该方法将委托给 ClassLoader.getSystemResource(java.lang.String)。

对我来说,这读作“Class.getResource实际上是在调用自己的classloader的getResource()”。这与做.但显然不是。有人可以给我一些关于这件事的启示吗?getClass().getClassLoader().getResource()


答案 1

Class.getResource可以采用“相对”资源名称,该名称相对于类的包进行处理。或者,可以使用前导斜杠指定“绝对”资源名称。类装入器资源路径始终被视为绝对路径。

所以下面基本上是等价的:

foo.bar.Baz.class.getResource("xyz.txt");
foo.bar.Baz.class.getClassLoader().getResource("foo/bar/xyz.txt");

这些也是如此(但它们与上述不同):

foo.bar.Baz.class.getResource("/data/xyz.txt");
foo.bar.Baz.class.getClassLoader().getResource("data/xyz.txt");

答案 2

第一个调用相对于文件进行搜索,而后者相对于类路径根进行搜索。.class

为了调试这样的问题,我打印了URL:

System.out.println( getClass().getResource(getClass().getSimpleName() + ".class") );

推荐