加载 .jar 资源时使用 ClassLoader
Using ClassLoader when loading .jar resources
我只是不明白为什么使用 ClassLoader 会导致这两种情况的行为不同。有人可以解释一下 how/why ClassLoader 更改了搜索,因此它需要进入 jar 的完整路径吗?
package com.example;
import java.io.InputStream;
public class SomeClass {
private static InputStream stm;
static {
for (final String s : new String[] { "file.png", "com/example/file.png", "/com/example/file.png" }) {
// case 1 - w/o classLoader
stm = SomeClass.class.getResourceAsStream(s);
System.out.println("w/o : " + (stm == null ? "FAILED to load" : "loaded") + " " + s);
// case 2 - w/ classLoader
stm = SomeClass.class.getClassLoader().getResourceAsStream(s);
System.out.println("w/classloader: " + (stm == null ? "FAILED to load" : "loaded") + " " + s);
}
}
public static void main(final String args[]) {}
}
生产:
w/o : loaded file.png
w/classloader: FAILED to load file.png
w/o : FAILED to load com/example/file.png
w/classloader: loaded com/example/file.png
w/o : loaded /com/example/file.png
w/classloader: FAILED to load /com/example/file.png
因为根据您调用的 getResourceAsStream()
方法,路径的评估方式不同。
如果您在 class com.example.SomeClass
上调用 Class.getResourceAsStream()
,那么如果路径不以 /
开头,则相对于 SomeClass
评估路径,因此 file.png
变为 /com/example/file.png
并且 com/example/file.png
变为 /com/example/com/example/file.png
.
如果你在它的 ClassLoader
上调用 ClassLoader.getResourceAsStream()
,那么路径是隐含的绝对路径并且不能以 /
开头,所以 file.png
变成 /file.png
和 com/example/file.png
变成 /com/example/file.png
.
如果你使用像/com/example/file.png
这样的绝对路径,你必须使用Class
方法。
不幸的是,ClassLoader.getResourceAsStream()
的这种隐式绝对性仅在 Class.getResourceAsStream()
的文档中隐式记录,其中指出它在委托给 ClassLoader
s 方法之前去除了前导斜线。
我只是不明白为什么使用 ClassLoader 会导致这两种情况的行为不同。有人可以解释一下 how/why ClassLoader 更改了搜索,因此它需要进入 jar 的完整路径吗?
package com.example;
import java.io.InputStream;
public class SomeClass {
private static InputStream stm;
static {
for (final String s : new String[] { "file.png", "com/example/file.png", "/com/example/file.png" }) {
// case 1 - w/o classLoader
stm = SomeClass.class.getResourceAsStream(s);
System.out.println("w/o : " + (stm == null ? "FAILED to load" : "loaded") + " " + s);
// case 2 - w/ classLoader
stm = SomeClass.class.getClassLoader().getResourceAsStream(s);
System.out.println("w/classloader: " + (stm == null ? "FAILED to load" : "loaded") + " " + s);
}
}
public static void main(final String args[]) {}
}
生产:
w/o : loaded file.png
w/classloader: FAILED to load file.png
w/o : FAILED to load com/example/file.png
w/classloader: loaded com/example/file.png
w/o : loaded /com/example/file.png
w/classloader: FAILED to load /com/example/file.png
因为根据您调用的 getResourceAsStream()
方法,路径的评估方式不同。
如果您在 class com.example.SomeClass
上调用 Class.getResourceAsStream()
,那么如果路径不以 /
开头,则相对于 SomeClass
评估路径,因此 file.png
变为 /com/example/file.png
并且 com/example/file.png
变为 /com/example/com/example/file.png
.
如果你在它的 ClassLoader
上调用 ClassLoader.getResourceAsStream()
,那么路径是隐含的绝对路径并且不能以 /
开头,所以 file.png
变成 /file.png
和 com/example/file.png
变成 /com/example/file.png
.
如果你使用像/com/example/file.png
这样的绝对路径,你必须使用Class
方法。
不幸的是,ClassLoader.getResourceAsStream()
的这种隐式绝对性仅在 Class.getResourceAsStream()
的文档中隐式记录,其中指出它在委托给 ClassLoader
s 方法之前去除了前导斜线。