类加载器介绍:http://fengchj.com/?p=2071、
深入理解类加载器:https://www.ibm.com/developerworks/cn/java/j-lo-classloader/index.html
类加载器源码分析:http://www.hollischuang.com/archives/199
知识扩展:
Class.getResource和ClassLoader.getResource的区别分析?
Class.getResource(String path):
Test.class.getResource("")默认是从此类所在的包下取资源
Test.class.getResource("/")则是从项目的ClassPath根下获取资源
ClassLoad.getResource(String path):
path不能以'/'开头时,path是指类加载器的加载范围,在资源加载的过程中,使用的逐级向上委托的形式加载的,'/'表示Boot ClassLoader中的加载范围,因为这个类加载器是C++实现的,所以加载范围为null
Test.class.getClassLoader().getResource("/")返回null
Class.getResource和ClassLoader.getResource本质上是一样的,并且Class.getResource的实现时考虑类加载器为null的情况,直接使用更方便。至于为什么Class.getResource(String path)中path可以'/'开头,是因为在name = resolveName(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; }