不求流芳百世,只求口碑载道
写在前面的话
反射作为java的核心基础之一是肯定要掌握的,虽然业务开发用的不多但是不代表它不重要。正所谓手中有粮心中不慌,本系列文章主要就是为了巩固和夯实反射知识点,为之后学习框架的编写打好基础。
一、反射相关
1、反射概念
反射是Java被视为动态语言的关键,反射机制允许程序在执行期间借助Reflection API获取任何类的内部信息,并能直接操作任意对象的内部属性及方法。
加载完类之后,在堆内存的方法区会产生一个Class类型的对象(一个类只有一个Class对象),这个对象包含了完成的类的结构信息,我们可以通过这个对象看到类的结构。
正常方式是:引入需要的包,通过new实例化,得到实例化的对象。
反射方式是:通过调用实例化对象的getClass()方法得到对象的全类名。
2、反射框架中常见方法
// 代表一个类
java.lang.Class
// 调用class对象的newInstance()返回一个对象实例
java.lang.Class#newInstance
// 代表类的方法,包括该类和超类中那些公共成员方法
java.lang.Class#getMethods
// 代表类的方法,包括公共、保护、默认(包)访问和私有方法,不包含超类的方法
java.lang.Class#getDeclaredMethods
// 代表类的字段,获得类的所有的public字段,包括父类
java.lang.Class#getFields
// 代表类的字段,获得类的所有声明的字段,即包括public、private、default、protected 不包括父类
java.lang.Class#getDeclaredFields
// 返回所有的包括私有构造方法,不包含超类
java.lang.Class#getDeclaredConstructors
// 只返回public访问权限的构造方法,不包含超类
java.lang.Class#getConstructors
二、反射相关API
1、获取Class类实例三种方法
// 1. 直接调用类的class属性获取
Class aClass = DictResponse.class;
// 2. 已知一个类的实例,调用该实例的getClass()获取
DictResponse response = new DictResponse();
Class<? extends DictResponse> responseClass = response.getClass();
// 3. 已知类的全类名 调用Class的类方法forName()获取
Class<?> aClass1 = Class.forName("reflect.DictResponse");
打印出hashcode,发现一致。所以验证了前面说的一个类只有一个Class对象。
2、获取类的运行时结构
写一个实体类DictResponse
public class DictResponse{
private Long id;
private String name;
private BigDecimal price;
// 忽略构造函数和get,set方法
}
// reflect.DictResponse
// DictResponse
DictResponse dictResponse = new DictResponse();
Class<? extends DictResponse> aClass = dictResponse.getClass();
System.out.println(aClass.getName());
System.out.println(aClass.getSimpleName());
// 打印出所有方法(构造方法,get,set,toString)
Method[] declaredMethods = aClass.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
// 打印该类所有属性
// private java.lang.Long reflect.DictResponse.id
// private java.lang.String reflect.DictResponse.name
// private java.math.BigDecimal reflect.DictResponse.price
Field[] declaredFields = aClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
注意:这里发现打印出来的属性全部是private,这时仅仅是能拿到属性但是不可以操作!
// 我们给id属性set值,会报异常
// Class reflect.ReflectMain can not access a member of class reflect.DictResponse with modifiers "private"
// declaredField.setAccessible(true) 设置暴力破解修饰符使得可以访问并使用私有属性
Field[] declaredFields = aClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
//declaredField.setAccessible(true);
if (declaredField.getType().equals(Long.class)) {
declaredField.set(dictResponse, 1L);
System.out.println(dictResponse.toString());
}
}
先到此为止,后续会有反射获取泛型结构信息及invoke()方法说明。