类加载器
类加载过程图
程序说明
/**
* @author tsz
* Date: 2020-10-08
* Time: 0:53
*/
public class Car {
public static void main(String[] args) {
/**
* 实例对象
*/
Car car1 = new Car();
Car car2 = new Car();
Car car3 = new Car();
System.out.println(car1.hashCode());
System.out.println(car2.hashCode());
System.out.println(car3.hashCode());
/**
* 类模板
*/
Class<? extends Car> carClass1 = car1.getClass();
Class<? extends Car> carClass2 = car2.getClass();
Class<? extends Car> carClass3 = car3.getClass();
System.out.println(carClass1.hashCode());
System.out.println(carClass2.hashCode());
System.out.println(carClass3.hashCode());
/**
* 输出结果
* 460141958
* 1163157884
* 1956725890
* 685325104
* 685325104
* 685325104
*/
}
}
这里可以看出:
- new 出的对象是不唯一的
- 类模板是全局唯一的
类加载器(Class Loader)
类加载器的种类
- 虚拟机自带的类加载器
- 启动类加载器 在 jre\lib\rt.jar
- 扩展类加载器 在jre\lib\ext 目录下
- 应用程序加载器
/**
* @author 谭绍宗
* Date: 2020-10-08
* Time: 0:53
*/
public class Car {
public static void main(String[] args) {
//获取类模板
Class<Car> carClass = Car.class;
//通过类模板getClassLoader() 获取了 AppClassLoader(应用程序加载器)
ClassLoader classLoader = carClass.getClassLoader();
System.out.println(classLoader);
//类加载器getParent()获取了ExtClassLoader(扩展类加载器) 在jre 的 ext 包下
ClassLoader parent1 = classLoader.getParent();
System.out.println(parent1);
// 输出null 但是其实是去调用C C++的接口了 java 无法读取到
ClassLoader parent2 = parent1.getParent();
System.out.println(parent2);
/**
* 输出
*sun.misc.Launcher$AppClassLoader@18b4aac2
* sun.misc.Launcher$ExtClassLoader@1b6d3586
* null
*/
}
}
双亲委派机制
代码说明
package java.lang;
/**
* @author tsz
* Date: 2020-10-08
* Time: 1:18
*/
public class String {
public String toString(){
return "你好呀";
}
public static void main(String[] args) {
String s = new String();
}
/**
* 报错
*
* 错误: 在类 java.lang.String 中找不到 main 方法, 请将 main 方法定义为:
* public static void main(String[] args)
* 否则 JavaFX 应用程序类必须扩展javafx.application.Application
*/
}
说明:
当我们写一个String类的时候在这个类进行加载的时候AppClassLoader收到类加载的请求,AppClassLoader会将这个请求向上委派给ExtClassLoader,然后ExtClassLoader接着委派给启动加载器因为启动类加载器在rt.jar下的java.lang包下找到了String这个类,所以最后加载的是jdk的java.lang.String 这个类而不是我们自己写的类 当要执行main 方法的 时候报了一个中找不到 main 方法的错误
注意:
当父类加载器无法加载到要加载的类的时候这个时候就会反着来让相应的类加载器加载类,如果无法加载到要加载的类那么就会抛出异常