一、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; }