反射机制

什么是反射(Reflection)

反射是指程序在运行时动态获取对象属性与方法的一种机制, 即编译器需要将类型信息(属性类型与偏移地址以及成员函数的地址等信息)编译到程序文件中, 当程序运行时将这些信息加载到内存中去, 做到运行时只根据对象的地址或引用就可以获取到对象的类型信息,从而利用这些信息达到修改或重建对象的目标.

在JAVA中的反射原理

Class类

除了int等基本类型外, Java的其他类型全部都是class(包括interface). 例如: String, Object, Runable.

那么class的本质是数据类型(Type). 无继承关系的数据类型无法赋值.

1
2
Number n = new Double(123.456)
String s = new Double(123.456)

class是由JVM在执行过程中动态加载的. JVM在第一次读取到一种class类型是, 将其加载到内存.

每加载到一种class, JVM就为其创建一个Class类型的实例, 并关联起来. 注意: 这里的class是一个名叫Classclass. 它长这样

1
2
3
public final class Class {
private Class(){}
}

String类为例, 当JVM加载String类时, 它首先读取String.class文件到内存, 然后,为String类创建一个Class实例并关联起来

1
Class cls = new Class(String)

这个Class实例是JVM内部创建的, 如果我们查看JDK源码, 可以发现Class类的构造方法是private, 只有JVM能创建Class实例, 我们自己的Java程序是无法创建Class实例的.

所以, JVM持有的每个Class实例都指向一个数据类型(Class或interface)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
┌───────────────────────────┐
│ Class Instance │──────> String
├───────────────────────────┤
│name = "java.lang.String" │
└───────────────────────────┘
┌───────────────────────────┐
│ Class Instance │──────> Random
├───────────────────────────┤
│name = "java.util.Random" │
└───────────────────────────┘
┌───────────────────────────┐
│ Class Instance │──────> Runnable
├───────────────────────────┤
│name = "java.lang.Runnable"│
└───────────────────────────┘

一个Class实例包含了该Class的所有完整信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
┌───────────────────────────┐
│ Class Instance │──────> String
├───────────────────────────┤
│name = "java.lang.String" │
├───────────────────────────┤
│package = "java.lang" │
├───────────────────────────┤
│super = "java.lang.Object" │
├───────────────────────────┤
│interface = CharSequence...│
├───────────────────────────┤
│field = value[],hash,... │
├───────────────────────────┤
│method = indexOf()... │
└───────────────────────────┘

由于JVM为每个加载的class创建了对应的class实例, 并在实例中保存了该class的所有信息, 包括类名, 包名, 父类, 实现的接口, 所有方法, 字段等, 因此, 如果获取了某个class实例, 我们就可以通过这个class实例获取到该实例对应的class的所有信息.

这种通过class实例获取class信息的方法称为反射(Reflection)

获取class的Class实例看文档或这个吧Class类

反射操作

对于任意一个Object实例, 只要获取了它的Class, 就可以获取它的一切信息

具体看文档或这个吧廖雪峰的JAVA教程

C++反射

编译期反射

运行期反射