一、Class的getResource(String path):URL
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; //父加载器非null if (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(); }