Java中的资源加载总是搞不清楚。今天刻意再稍微看了一下,但是还是没有深入了解。因为要彻底搞清楚必须深刻理解ClassLoader和URL才行。现在只能写一点自己的心得。
首先给出例子,通过例子可以帮助一些人立即解决问题。在Eclipse中我们新建如下图所示的工程。
其中:
test.properties内容为:hello=world
test2.properties内容为:hello=world2
test3.properties内容为:hello=world3
ClassLoaderTest内容如下:
package edu.xjtu.ctec.test;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class ClassLoaderTest {
public static void main(String[] args) throws IOException {
testLoad1();
testLoad2();
testLoad3();
}
private static void testLoad3() throws IOException {
System.out.println("----test load3-----");
String filename = "test3.properties";
InputStream input1 = ClassLoaderTest.class.getResourceAsStream("../../../../" + filename);
print(input1);
InputStream input2 = ClassLoaderTest.class.getResourceAsStream("/" + filename);
print(input2);
InputStream input3 = ClassLoaderTest.class.getClassLoader().getResourceAsStream(filename);
print(input3);
}
private static void testLoad2() throws IOException {
System.out.println("----test load2-----");
String filename = "test2.properties";
InputStream input1 = ClassLoaderTest.class.getResourceAsStream("config/" + filename);
print(input1);
InputStream input2 = ClassLoaderTest.class.getResourceAsStream("/edu/xjtu/ctec/test/config/" + filename);
print(input2);
InputStream input3 = ClassLoaderTest.class.getClassLoader().getResourceAsStream("edu/xjtu/ctec/test/config/" + filename);
print(input3);
}
private static void testLoad1() throws IOException {
System.out.println("----test load1-----");
String filename = "test.properties";
InputStream input1 = ClassLoaderTest.class.getResourceAsStream(filename);
print(input1);
InputStream input2 = ClassLoaderTest.class.getResourceAsStream("/edu/xjtu/ctec/test/"+ filename);
print(input2);
InputStream input3 = ClassLoaderTest.class.getClassLoader().getResourceAsStream("edu/xjtu/ctec/test/" + filename);
print(input3);
}
private static void print(InputStream input) throws IOException {
Properties properties = new Properties();
properties.load(input);
String world = (String) properties.get("hello");
System.out.println(world);
}
}输出结果为:
----test load1-----
world
world
world
----test load2-----
world2
world2
world2
----test load3-----
world3
world3
world3
world
world
world
----test load2-----
world2
world2
world2
----test load3-----
world3
world3
world3
根据上面的结果总结如下:
Class.getResourceAsStream传入的路径可以有两种方式:
(1)不以“/”开头,则是相对与类所在的包找寻资源文件;如加载test.propertis时为: ClassLoaderTest.class.getResourceAsStream("test.properties");
(2)如果以“/”开头,则从当前路径开始查找,当前路径即src(当然实际上运行的时候是编译类的目的地,通常可能是您设置的bin,这里说src只是方便用户定位的,因为源代码下面的资源文件会拷贝到类所在的位置)。如加载test.properties时为
ClassLoaderTest.class.getResourceAsStream("/edu/xjtu/ctec/test/test.properties");
ClassLoader.getResourceAsStream传入的路径则统一是从当前路径开始查找的,跟Class的第二种加载方式区别在于不能以"/"开始。所以加载test.properties为
ClassLoaderTest.class.getClassLoader.getResourceAsStream("edu/xjtu/ctec/test/test.properties");
Class加载资源的时候会委托给相应的ClassLoader来加载的,不过之前会对路径进行一些处理(见下面代码中的resolveName)。下面是Class.getResourceAsStream的源代码。
public InputStream getResourceAsStream(String name) {
name = resolveName(name);
ClassLoader cl = getClassLoader0();
if (cl==null) {
// A system class.
return ClassLoader.getSystemResourceAsStream(name);
}
return cl.getResourceAsStream(name);
}
private String resolveName(String name) {
if (name == null) {
return name;
}
if (!name.startsWith("/")) {
Class c = this;
while (c.isArray()) {
c = c.getComponentType();
}
String baseName = c.getName();
int index = baseName.lastIndexOf('.');
if (index != -1) {
name = baseName.substring(0, index).replace('.', '/')
+"/"+name;
}
} else {
name = name.substring(1);
}
return name;
}
而ClassLoader则委托其父类加载器在ClassPath下查找资源。具体的就没有深入 了。
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>

4014





