Class.getResource()和ClassLoader.getResource()之间有什么区别?
我想知道Class.getResource()
和ClassLoader.getResource()
之间有什么区别?
编辑:我特别想知道是否有任何caching文件/目录级别涉及。 如“在Class版本中caching的目录列表?
以下AFAIK基本上应该做同样的事情,但他们不是:
getClass().getResource() getClass().getClassLoader().getResource()
我在摆弄某些报告生成代码时发现了这个问题,这些代码在WEB-INF/classes/
从该目录中的现有文件中创build一个新文件。 当使用Class中的方法时,我可以使用getClass().getResource()
查找在部署时存在的文件,但是当试图获取新创build的文件时,我收到一个空对象。 浏览目录清楚地显示新文件在那里。 如“/myFile.txt”中的文件名前加斜杠。
另一方面, getResource()
的ClassLoader
版本find了生成的文件。 从这个经验看来,目录列表正在进行某种caching。 我是对的吗?如果是的话,这是在哪里logging?
从Class.getResource()
的API文档
查找具有给定名称的资源。 用于search与给定类关联的资源的规则由类的定义类加载器来实现。 这个方法委托给这个对象的类加载器。 如果此对象由引导类加载器加载,则该方法委托给ClassLoader.getSystemResource(java.lang.String)。
对我来说,这读取“Class.getResource真的调用自己的类加载器的getResource()”。 这和getClass().getClassLoader().getResource()
。 但显然不是。 有人能给我提供一些关于这个问题的启示吗?
回答是否有任何caching正在进行。
我通过运行独立的Java应用程序进一步调查了这一点,该应用程序使用getResourceAsStream ClassLoader方法从磁盘连续加载文件。 我能够编辑文件,并立即反映更改,即该文件是从磁盘重新加载没有caching。
但是:我正在做一个项目,有几个相互依赖的Maven模块和Web项目。 我使用IntelliJ作为我的IDE来编译和运行Web项目。
我注意到,上述似乎不再成立,原因是我正在加载的文件现在被烘焙成一个jar子,并部署到相关的Web项目。 我只是在尝试更改目标文件夹中的文件时才注意到这一点,但无济于事。 这使得好像caching正在进行。
Class.getResource
可以采用一个“相对”的资源名称,这个名字是相对于类的包来处理的。 或者,您可以使用前导斜杠指定“绝对”资源名称。 类加载器资源path总是被认为是绝对的。
所以它们基本上是等价的:
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");
第一次调用相对于.class
文件进行search,而后者则相对于类path根进行search。
要debugging这样的问题,我打印url:
System.out.println( getClass().getResource(getClass().getSimpleName() + ".class") );
必须查看它的规格:
-
Class.getResource(String资源)
-
ClassLoader.getResource(String资源)
类的getResource() – 文档指出了区别:
在对资源名称进行这些更改后,此方法将调用委托给其类加载器:如果资源名称以“/”开头,则不变; 否则,在转换“。”之后,软件包名称会预先添加到资源名称中。 至 ”/”。 如果此对象由引导加载程序加载,则该调用将委托给ClassLoader.getSystemResource。
这里的所有答案,以及这个问题的答案都表明,加载绝对的URL,比如“/foo/bar.properties”,通过class.getResourceAsStream(String)
和class.getClassLoader().getResourceAsStream(String)
。 这不是这种情况,至less不是我的Tomcatconfiguration/版本(目前是7.0.40)。
MyClass.class.getResourceAsStream("/foo/bar.properties"); // works! MyClass.class.getClassLoader().getResourceAsStream("/foo/bar.properties"); // does NOT work!
对不起,我绝对没有令人满意的解释,但我猜测,tomcat与类加载程序做脏伎俩和黑魔法,造成差异。 我以前总是使用class.getResourceAsStream(String)
,并没有任何问题。
PS:我也在这里发布
我尝试从input1.txt中读取与我正在尝试读取它的类一起在我的包中。
以下工作:
String fileName = FileTransferClient.class.getResource("input1.txt").getPath(); System.out.println(fileName); BufferedReader bufferedTextIn = new BufferedReader(new FileReader(fileName));
最重要的部分是要调用getPath()
如果你想正确的path名string格式。 不要使用toString()
因为它会添加一些额外的格式化文本,这将完全使用fileName(你可以试试看,看看打印出来)。
花了2小时debugging这个… 🙁
Class.getResources将通过加载对象的类加载器来检索资源。 而ClassLoader.getResource将使用指定的类加载器来检索资源。