一、Class的getResource(String path):URL
View Code
View Code
1、path 不以’/'开头时,默认是从此类所在的包下取资源; 2、path 以’/'开头时,则是从ClassPath根下获取;
System.out.println(Test.class.getResource("")); System.out.println(Test.class.getResource("/"));
file:/E:/java/Test/bin/cn/ file:/E:/java/Test/bin/
二、类加载器ClassLoader的getResource(String path)
1、path 不以'/'开头
path是指类加载器的加载范围,在资源加载的过程中,使用的逐级向上委托的形式加载的,加载范围是从整个ClassPath范围。
2、path 以'/'开头
'/'表示Boot ClassLoader中的加载范围,因为这个类加载器是C++实现的,所以加载范围为null。
System.out.println(Test.class.getClassLoader().getResource("")); System.out.println(Test.class.getClassLoader().getResource("/"));
file:/E:/java/Test/bin/
null
三、class.getResource("/") 等价于 class.getClassLoader().getResource("")
class.getResource()与classLoader().getResource()最终使用了系统类加载器加载以classpath为根的不带'/'的路径进行加载资源
Class的getResource方法源码
public URL getResource(String name){name = resolveName(name);//将路径转换成为classpath根的绝对路径,不以/开头ClassLoader cl = getClassLoader0();if (cl==null){// A system class.return ClassLoader.getSystemResource(name);}return cl.getResource(name); }
getClassLoader0方法与resolveName方法

//获取当前类的类加载器 ClassLoader getClassLoader0(){return classLoader; }//获取classpath根的绝对路径,不以/开头 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.getSystemResource方法

public static URL getSystemResource(String name) {//返回委派的系统类加载器。这是默认代表团的父母新的类加载器实例,并通常用于启动应用程序的类加载器。ClassLoader system = getSystemClassLoader();if (system == null) {return getBootstrapResource(name);//根据根加载器的路径检索资源 }return system.getResource(name); } // The class loader for the system private static ClassLoader scl; public static ClassLoader getSystemClassLoader() {initSystemClassLoader();if (scl == null) {return null;}SecurityManager sm = System.getSecurityManager();if (sm != null) {checkClassLoaderPermission(scl, Reflection.getCallerClass());}return scl; }
ClassLoader.getResource方法源码
private final ClassLoader parent; public URL getResource(String name) {URL url;//父加载器非nullif (parent != null) {url = parent.getResource(name); //请求父加载器获取资源} else {url = getBootstrapResource(name); //该类为ExtClassLoader,用其父加载器Bootstrap加载资源 }if (url == null) {url = findResource(name);}return url; } //从虚拟机的内置类加载器查找资源 private static URL getBootstrapResource(String name) {URLClassPath ucp = getBootstrapClassPath();Resource res = ucp.getResource(name); return res != null ? res.getURL() : null; }//返回urlclasspath是用于发现系统资源。 static URLClassPath getBootstrapClassPath() {return sun.misc.Launcher.getBootstrapClassPath(); }