反射的原理
# 反射的原理
要了解反射,就得先知道 Java 代码在运行时期的三个阶段
- 源代码阶段:Person.java 和 Person.class 都在硬盘上,还没进入内存
- Class 类对象阶段:通过类加载器,将字节码文件加载进内存,万物皆对象,用 CLass 对象来描述 class 文件。该对象用来描述所有字节码文件的。
- Runtime 运行时阶段
Person.class 里面包含了类的名字、类的成员变量、类的构造方法和类的成员方法等。
# 源代码阶段
例如定义一个类 Person
public class Person{
public String name;
private int age;
public Person(){}
public void eat(){}
}
1
2
3
4
5
6
2
3
4
5
6
Person.java
↓
通过 Javac 命令编译
↓
Person.class 字节码文件,里面存放了三类重要的方法
- 类的成员变量
- 构造方法
- 方法
Person.java 和 Person.class 都是文件,还没被加载进内存。
# CLass 类对象阶段
类加载器 ClassLoader 将字节码文件加载进内存。因为我们要创建一个对象,那么首先得知道这个类有什么信息,例如有什么成员变量、有什么构造方法和普通方法,这样我们才能创建对象。
那么,这个类的信息用什么来表示呢?在 Java 中,万物皆对象,有个类的名字就是 Class,用来表示字节码文件里的信息
Class Class<T>
1
我们平时用的 String 类型,Random 类型,都是靠 Class 对象来创建实例的:
┌───────────────────────────┐
│ Class Instance │──────> String
├───────────────────────────┤
│name = "java.lang.String" │
└───────────────────────────┘
┌───────────────────────────┐
│ Class Instance │──────> Random
├───────────────────────────┤
│name = "java.util.Random" │
└───────────────────────────┘
┌───────────────────────────┐
│ Class Instance │──────> Runnable
├───────────────────────────┤
│name = "java.lang.Runnable"│
└───────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
不管什么字节码文件,都有
- 成员变量 封装为 Field 对象,由于有多个,用 Field[] fields 表示
- 构造方法 封装为 Constructor 对象,由于有多个,用 Constructor[] con 表示
- 成员方法 封装为 Method 对象,由于有多个,用 Method[] methods 表示
┌───────────────────────────┐
│ Class Instance │──────> String
├───────────────────────────┤
│name = "java.lang.String" │
├───────────────────────────┤
│package = "java.lang" │
├───────────────────────────┤
│super = "java.lang.Object" │
├───────────────────────────┤
│interface = CharSequence...│
├───────────────────────────┤
│field = value[],hash,... │
├───────────────────────────┤
│method = indexOf()... │
└───────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
而这些信息,也都是用对象来表示的。
所以我们后续就围绕这几个类来学习:
Class
:任何运行在内存中的所有类都是该 Class 类的实例对象,每个 Class 类对象内部都包含了本来的所有信息。记着一句话,通过反射干任何事,先找 Class 准没错!可以说通过Class
实例获取class
信息的方法称为反射(Reflection)。Field
:描述一个类的属性,内部包含了该属性的所有信息,例如数据类型,属性名,访问修饰符······Constructor
:描述一个类的构造方法,内部包含了构造方法的所有信息,例如参数类型,参数名字,访问修饰符······Method
:描述一个类的所有方法(包括抽象方法),内部包含了该方法的所有信息,与Constructor
类似,不同之处是 Method 拥有返回值类型信息,因为构造方法是没有返回值的。
# 运行时阶段
此时类已被加载进内存,可以 new 对象了。
换句话说,也就是我们可以通过类加载器获取到某个类的信息(有什么成员变量、构造方法和普通方法),然后就可以通过它使用该类了
关于类加载器,我们这里不展开,后续再说。
上次更新: 2024/10/1 18:45:09