反射
一、类的加载、连接和初始化
- 当调用Java命令运行某个Java程序时,该命令会启动一个Java虚拟机进程,不管该Java程序有多么复杂,该程序启动的线程都处于该Java虚拟机进程里
- 当程序使用某个类时,如果该类还未被加载到内存中,则系统会通过加载、连接、初始化三个步骤来初始化该类
- 类的加载:当程序中使用某个类时,系统都会为之建立一个
java.lang.Class
对象,系统中所有类都是java.lang.Class
的实例 - 类的连接:把类的二进制数据合并到
JRE
中- 验证:检验被加载类是否有正确的内部结构,并和其他类协调一致
- 准备:为类变量分配内存并设置默认初始值
- 解析:将类的二进制数据中的符号引用替换成直接引用
- 类的初始化:对类变量进行初始化,可以在声明类变量时指定初始值,或在静态初始化块中指定初始值。类初始化包含以下几个步骤
- 如果这个类还没有被加载和连接,则先加载并连接该类
- 如果该类的直接父类还没被初始化,则先初始化其直接父类
- 如果类中有初始化语句,则按顺序执行这些初始化语句
- 类的加载:当程序中使用某个类时,系统都会为之建立一个
二、类加载器
- 类加载器负责将
.class
文件加载到内存中,并为之生成对应的java.lang.Class
对象,一旦一个类被载入JVM中,就不会被再次载入了,一个类用其全限定类名和其类加载器作为唯一标识 - 在JVM中,类加载器层次结构由三个类加载器组成,同时开发人员可以自定义类加载器
Bootstrap ClassLoader
:根类加载器,加载Java核心类Extension ClassLoader
:扩展类加载器System ClassLoader
:系统类加载器
三、通过反射查看类信息
- 一旦获得某个类所对应的
Class
对象之后,就可以调用其方法来获得该类的真实信息
- 使用
Class
类的forName(String clazzName)
静态方法 - 调用某个类的
Class
属性来获得该类对应的Class
对象 - 调用某个对象的
getClass()
方法,该方法是Object
类中的一个方法
Class
、interface
、Enum
、@interface
、primitive type
、[]
、void
都可以有Class
对象
四、使用反射生成并操作对象
Class
对象可以获得该类里的方法(Method
)、构造器(Constructor
)、成员变量(field
),这三个类都位于java.lang.reflect
包下,并实现了java.lang.reflect.Member
接口。程序可以通过Method
对象来执行对应的方法,通过Constructor
对象来调用对应的构造器创建实例,通过Field
对象直接访问并修改对象的成员变量值
五、动态代理
- 动态代理在
AOP(Aspect Orient Programming,面向切面编程)
中被称为AOP代理,AOP代理可代替目标对象,AOP代理包含了目标对象的全部方法