Java反射
大约 3 分钟
1. 反射基础
Java的反射机制可以将成员变量、方法、构造方法、包等信息映射成对象。
1.1 Class类
- Class也是一种类,每个Java类都在JVM中表现为一个Class对象,可以通过
类名.class
、对象.getClass()
、Class.forName(类名)
等方法获取Class对象 - 类在编译后会产生Class对象,保存在
同名.class
的字节码文件中 - Class类的作用是在运行时获取对象的信息
1.2 Class对象的获取
获取class对象爱哪个的方式有三种:
- 根据类名:类名.class
- 根据对象:对象.getClass()
- 根据全限定类名:Class.forName(全限定类名)
// 获取Class对象的三种方式
logger.info("根据类名: \t" + User.class);
logger.info("根据对象: \t" + new User().getClass());
logger.info("根据全限定类名:\t" + Class.forName("com.test.User"));
在获取类名之后,可以对其进行操作,常用的方法有:
- 获取全限定类名:class.getName();
- 获取类名:class.getSimpleName();
- 实例化对象: class.newInstance();
// 常用的方法
logger.info("获取全限定类名:\t" + userClass.getName());
logger.info("获取类名:\t" + userClass.getSimpleName());
logger.info("实例化:\t" + userClass.newInstance());
1.3 Constructor
Constructor类反映的是Class 对象所表示的类的构造方法:
- 创建实例:newInstance()
- 获取指定参数的public构造函数:getConstructor(Class<?>... parameterTypes)
1.4 Field
Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段,可以通过Class来获取:
- 获取指定名称的(包含private,不包含继承)的字段:getDeclaredField(String name)
- 获取Class对象所表示的类或接口的所有(包含private修饰的)字段,不包括继承的字段:getDeclaredFields()
- 获取指定name名称、具有public修饰的字段,包含继承字段:getField(String name)
- 获取修饰符为public的字段,包含继承字段:getFields()
1.5 Method
Method 提供关于类或接口上单独某个方法(以及如何访问该方法)的信息,所反映的方法可能是类方法或实例方法(包括抽象方法):
- 返回一个指定参数的Method对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法:getDeclaredMethod(String name, Class<?>... parameterTypes)
- 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法:getMethod(String name, Class<?>... parameterTypes)
- 返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法:getMethods()
2. 反射的执行流程
- 程序调用相关方法获取class的类信息,此时将在JVM中获取ClassLoader,并最后返回class对象
- 程序调用class.newInstance(),随后由JVM进行类的初始化,并返回Object
- 程序调用class.getMethod,由JVM加载所有的方法,copy一份并返回
- 程序调用method.invoker(),最终由JVM执行invoke0()