文章目录
一、类加载器
两个类是同一个类 = 两个类用的类加载器相同 + 类本身的全限定名相同
1.三种类加载器
-
Bootstrap ClassLoader 根类加载器(引导类加载器)
引导类加载器(由C++语言编写)由操作系统的本地代码来实现,这个类加载器没有父类加载器。之所以会出现引导类加载器,是因为其他两个类加载器也需要类加载器来加载。它负责Java核心类的加载,比如System,String等。 -
Extension ClassLoader 扩展类加载器
扩展类加载器(由Java语言编写)主要负责扩展路径下的代码,负责JRE的扩展目录中jar包的加载。它的父类加载器是根类加载器。 -
System ClassLoader 系统类加载器
系统类加载器(由Java语言编写)也称为应用类加载器(APPClassLoader),这两个是等价的。负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径。它的父类加载器是扩展类加载器。 -
用户自定义类加载器
三种类加载器的关系图如下:
2.类加载器的内容
-
除了根类加载器以外,其他的类加载器都有且只有一个父类加载器。
-
当生成一个自定义的类加载器实例时,如果没有指定它的父加载器,那么系统类加载器将成为该类加载器的父类加载器。
-
类加载器只负载它的“祖先”无法加载的类。(双亲委派模型)
比如,若系统类加载器需要加载一个类,它首先委托它的父类加载器(扩展类加载器),然后扩展类加载器再委托它的父类加载器(根类加载器),如果父类加载器不能加载此类,那么子类加载器就会在自己的库中查找这个类,这样也使得安全性大大提升。
3.类加载器的双亲委派模型
(1)定义
在类加载的时候,系统会首先判断当前类是否被加载过。已经被加载的类会直接返回,否则才会尝试加载。加载的时候,首先会把该请求委派该父类加载器的 loadClass() 处理,因此所有的请求最终都应该传送到顶层的启动类加载器 BootstrapClassLoader 中。当父类加载器无法处理时,才由自己来处理。当父类加载器为null时,会使用启动类加载器 BootstrapClassLoader 作为父类加载器。
(2)双亲委派模型的优点
- 双亲委派模型保证了Java程序的稳定运行,可以避免类的重复加载(JVM 区分不同类的方式不仅仅根据类名,相同的类文件被不同的类加载器加载产生的是两个不同的类)。
- 保证了 Java 的核心 API 不被篡改。
二、反射
1.反射的定义
- 反射就是把Java类中的各种成分(成员变量,成员方法,构造器等)映射成相应的Java类。
- JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
- 反射一般会涉及如下类:Class(表示一个类的类)、Field(表示属性的类)、Method(表示方法的类)和Constructor(表示类的构造器的类)。
2.反射的基本应用
写在前面,对于IDEA使用反射时,要在File->Settings->Build,Execution,Deployment->Compiler->Java Compiler中的Additional command line parameters: 后面填上 -parameters,点击OK。
(1)获取Class类的对象(即得到相应类的字节码)
- 方法一:getClass()方法
Person p = new Person();
Class c = p.getClass();
- 方法二:通过 类名.class 获取到字节码文件对象(任意数据类型都具备一个class静态属性)
Class c2 = Person.class;
- 方法三:通过调用Class类中的静态方法forName()方法将类名作为字符串传递给Class类中的静态方法forName即可)
Class c3 = Class.forName("Person");
注: 前两种方法必须明确Person类型,方法三是指定这种类型的字符串就行。(方法三扩展更强,我不需要知道你的类.我只提供字符串,按照配置文件加载就可以了)</