Java资源加载
Java资源加载
我想知道Class.getResource()
和ClassLoader.getResource()
之间的区别是什么?
编辑:我特别想知道文件/目录级别是否涉及到缓存。比如说,“Class版本中的目录列表是否被缓存了?”
据我所知,下面的代码本质上应该是一样的,但实际上它们并不一样:
getClass().getResource() getClass().getClassLoader().getResource()
我是在处理一些报告生成代码时发现的这个问题。该代码从WEB-INF/classes/
目录中的现有文件创建一个新文件。当我使用Class的方法时,我可以通过getClass().getResource()
找到部署时存在的文件,但是当我尝试获取新创建的文件时,我收到了一个空对象。浏览目录清楚地显示新文件是存在的。文件名以斜杠开头,如“/myFile.txt”。
另一方面,ClassLoader
版本的getResource()
确实可以找到生成的文件。根据这个经验,似乎存在某种目录列表的缓存。我是对的吗?如果是这样,这在哪里有记录?
根据Class.getResource()
的API文档:
查找具有给定名称的资源。用于搜索与给定类关联的资源的规则由类的定义类加载器实现。此方法委托给此对象的类加载器。如果此对象是由引导类加载器加载的,则该方法委托给ClassLoader.getSystemResource(java.lang.String)。
对我来说,这意味着“Class.getResource实际上是调用它自己的类加载器的getResource()方法”。这与执行getClass().getClassLoader().getResource()
相同。但显然并不是这样。请问有人能给我一些关于这个问题的启示吗?
Java资源加载(Java resource loading)是一个常见的问题,出现的原因是因为在Java中,使用不同的方法加载资源会导致不同的搜索路径。具体来说,调用getClass().getResource()
方法会相对于.class
文件进行搜索,而调用getClassLoader().getResource()
方法会相对于类路径的根目录进行搜索。
为了调试这种问题,可以使用System.out.println()
语句打印URL,例如:System.out.println( getClass().getResource(getClass().getSimpleName() + ".class") );
。通过打印URL,可以更清楚地看到资源的搜索路径。
需要注意的是,如果文件名以/
开头,两种方法都可以搜索绝对路径。但是有趣的是,有时候getClass().getResource("/someAbsPath")
会返回一个形如/path/to/mylib.jar!/someAbsPath
的URL,而getClassLoader().getResource("/someAbsPath")
会返回null
。这表明"类加载器的根目录"并没有一个明确定义的概念。
如果想了解更多关于这个的问题,可以参考stackoverflow.com/questions/13269556/…。
Java资源加载问题的出现是因为在使用不同的方法加载资源时,搜索路径不一致。为了解决这个问题,可以根据具体的需求选择使用getClass().getResource()
或getClassLoader().getResource()
方法。