Java类加载器基于三个机制:委托、可见性和单一性。
委托机制是指将加载一个类的请求交给父类加载器,如果这个父类加载器不能够找到或者加载这个类,那么再加载它。
可见性的原理是子类的加载器可以看见所有的父类加载器加载的类,而父类加载器看不到子类加载器加载的类。
单一性原理是指仅加载一个类一次,这是由委托机制确保子类加载器不会再次加载父类加载器加载过的类。
正确理解类加载器能够理解NoClassDefFoundError和java.lang.ClassNotFoundException,因为它们和类的加载相关。Java类加载器和工作原理以及classpath如何运作的经常被问到。Java面试题中也经常出现“一个类是否能被两个不同类加载器加载”这样的问题。答案是肯定不行的。
下面来看一个例子:
首先自定义一个String类:
package Test.String;
public class String {
public String() {
System.out.println("test loader");
}
}
新建TestString类来进行测试:
package Test;
import java.lang.String;
import Test.String.String;
public class TestString {
/**
* 这种情况虚拟机根据双亲委托机制优先加载java.lang.String类,程序正常运行
*
*/
public static void main(String[] args) {
new String();
}
}
稍微改动下,不手动导入java.lang.String包,看看会发生什么。
package Test;
import Test.String.String;
public class TestString {
/**
* 这种情况虚拟机加载无法main入口,程序无法执行。因为main方法的String[]参数是自定义的类,不是java.lang.String
*
*/
public static void main(String[] args) {
new String();
}
}
所以记住不要自定义已有的类!!!
要让上面的方法可以运行,只需显示路径加载java.lang.String[]类型
package Test;
import Test.String.String;
public class TestString {
/**
* 这种情况mian函数参数String[]是java.lang.String类型的,程序可以正常运行
*
*/
public static void main(java.lang.String[] args) {
new String();
}
}