反射机制
:::warning
- 反射机制是非常难解释清楚的,主要原因有如下几个
- 反射机制概念本身就很抽象,难以理解其概念
- 反射机制在初学时使用的机会很少,因为初学者甚至都没有类加载的概念
- 反射机制涉及到虚拟机中类加载的概念,在各个框架中也有很广泛的应用,没有这些的基本了解真的很难理解
- 我会尽可能将反射最基础的内容和虚拟机联系起来
:::
:::primary
参考博客:Java基础篇:反射机制详解
:::
什么是类加载机制?
:::info
详细了解:Java 虚拟机-类加载机制
:::
什么是反射?
定义:
- [虚拟机处于 运行状态 中]{.red}
- [对于任意一个类都能够知道这个类所有的属性和方法]{.blue}
- [对于任意一个对象,都能够调用它的任意一个方法]{.blue}
核心:[在进程运行期间将类 动态 地加载到虚拟机内存中使用]{.red}
为什么要使用反射?
如何使用反射?
反射的原理是什么?
反射
概念解释
- Java 程序处于运行过程中
- 根据 Java 程序的需要
- 动态加载 .class 文件
- 图示解释
目的解释
- 更加灵活地根据需求加载 .class 文件
例:每个数据库系统都有不同的数据库驱动(MySQL Oracle);
如果在编写代码的时候无法确定程序在执行的过程中究竟使用哪一套数据库驱动系统;
采用反射机制使用 Class.forName(需要加载的类的全限定名)加载需要使用的数据库驱动
Java 成为准动态语言
|
反射的用途
- 创建实例
- 框架实现的原理
反射主要内容
Javac
基本概念:Javac 全称 Java Compiler
目的
Java 源代码实是由 Javac.exe 执行的
也就是说我们执行 Java 程序实际上是在执行 Javac.exe
Javac 将由 Java 语言编写的源代码 转换成 机器能够识别的 字节码文件(.class)

使用
类加载器
概念:将 C++ 和 Java 编写完成的 “类” 加载到堆中的方法区中生成 Class 对象
- 类:所有的类(.java)文件都被 Javac 编译成 .class 文件;所以实际类加载器加载的是 .class 文件
分类
- BootstrapClassLoader
- 功能:负责加载 Java 语言中的最核心的类库(java.lang.*) 和 构造 ExtClassLoader 和 APPClassLoader
- 特点
- C++编写
- 涉及到虚拟机的本地实现细节,不能够被直接调用
- ExtClassLoader
- 功能:负责加载 Java 语言中的扩展类库(javax.*)
- 特点
- Java 编写
- 开发者可以实际调用
- APPClassLoader
- 功能:主要负责加载应用程序的主函数类
- BootstrapClassLoader
类加载机制
图示

双亲委派机制
图示

解释
从 自定义类加载器 开始判断当前的类是否加载过;
如果当前的类已经在任何一个 类加载器中加载过了,那么当前类就不需要加载了
如果直到 核心类库加载器 中还没有加载过,那么开始从 核心类库加载器 开始判断当前类是否可以被加载
如果当前的类加载器无法加载那么依次向下提交,直到 自定义类加载器
如果连 自定义类加载器 都无法加载,那么证明当前的类是无法被加载的
目的
- 避免类的重复加载
- 避免基础核心类库被篡改(自行编写的 String 类是无法被加载的)
实例构建过程

Class 对象
- 概念:.class 文件被类加载器载入堆的方法区中生成 Class 对象
- 内容
- Class 对象具有被加载类的所有信息(注解,方法,字段,构造函数等)
- Class 对象提供 Method Field Constructor 等静态类存储方法,字段,构造器的所有信息
- 源代码
private static class ReflectionData<T> { |
API
- 获取类的方式
// 第一种方式 -- 任意情况都能够使用 |
- 获得构造器的方式
Constructor getConstructor(Class[] params) -- 获得使用特殊的参数类型的公共构造函数, |
- 获得字段的方式
Field getField(String name) -- 获得命名的公共字段 |
- 获得方法的方式
Method getMethod(String name, Class[] params) -- 使用特定的参数类型,获得命名的公共方法 |