类加载器:
1.应用程序加载器
2.扩展类加载器
3.根加载器也叫启动类加载器
首先,类被加载为.class字节码文件,然后由类加载器加载并进行初始化。
其中 Car类是模板,只有一个,是抽象的。Car的实例可以有多个,通过new关键字来实例化对象,对象是具体的。
那我们的程序是由哪个加载器加载的呢?通过代码演示一下
public class Car {
//类模板 只有一个,实例可以有多个
public static void main(String[] args) {
Car car1 = new Car();
Car car2 = new Car();
Car car3 = new Car();
Class<? extends Car> aClass1 = car1.getClass();
System.out.println(car1.hashCode());
System.out.println(car2.hashCode());
System.out.println(car3.hashCode());
System.out.println(car1.getClass().hashCode());
System.out.println(car2.getClass().hashCode());
System.out.println(car3.getClass().hashCode());
System.out.println(aClass1.getClassLoader());
System.out.println(aClass1.getClassLoader().getParent());
System.out.println(aClass1.getClassLoader().getParent().getParent());//null 1.没有 2.找不到
//底层是C、C++
}
可以看出Car类是由AppClassLoader加载的。
那什么时候会用别的加载器加载,这就涉及到双亲委派机制。
双亲委派机制
比如,我自己写了一个java.lang.String.
package java.lang;
public class String {
//双亲委派机制:安全
/*
* 一层层网上找
* 应用程序类加载器--扩展类--根
* 找不到再一层层回来 */
@Override
public String toString() {
return "hello";
}
public static void main(String[] args) {
String string = new String();
System.out.println(string.toString());
}
}
这是因为String类本来就在根加载器java.lang包下,一层层往上找,没有再依次回来。
所以这个类应该是由根加载器加载的。
双亲委派机制原理图