JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
通俗点讲,反射就是把java类中的各种成分映射成一个个的Java对象。
例如:类的class声明(class对象),变量(field),方法(method)等等信息,利用反射技术可以对一个类进行解剖,动态获取信息进行处理。
1、获取Class对象的三种方式
1.1 Object ——> getClass();
TextMessage text = new TextMessage();
Class extends TextMessage> clazz = text.getClass();
1.2 任何数据类型(包括基本数据类型)都有一个“静态”的class属性
Classclazz = TextMessage.class;
1.3 通过Class类的静态方法:forName(String className)(常用)
Class clazz = Class.forName("com.demo.TextMessage");
3. ReflectionUtils常见方法使用
//通过属性名称name和类型type,从clazz获取field public static Field findField(Class clazz, String name, Class type) //通过属性名称name,从clazz获取field public static Field findField(Class clazz, String name) //给对应target对象的field赋值value public static void setField(Field field, Object target, Object value) //根据属性字段field和对象target,获取的对象中字段的值 public static Object getField(Field field, Object target) //根据类,方法名称和参数类型查找方法 public static Method findMethod(Class clazz, String name) //根据类,方法名称和参数类型查找方法 public static Method findMethod(Class clazz, String name, Class[] paramTypes) //调用target对象的方法,无入参 public static Object invokeMethod(Method method, Object target) //调用target对象的方法,入参为args public static Object invokeMethod(Method method, Object target, Object[] args) //判断属性是否包含特定修饰符 public static boolean isPublicStaticFinal(Field field) //让属性可以访问,主要针对私有属性 public static void makeAccessible(Field field)4. ReflectionUtils实现源码demo分析
findField方法根据类型,字段名称和字段类型查询一个字段,主要实现就是遍历的向父类获取clazz所有的field,然后进行name和type的匹配,进而找到对应的field。
public static Field findField(Class> clazz, String name, Class> type) {
Class> searchType = clazz;
while (Object.class != searchType && searchType != null) {
Field[] fields = getDeclaredFields(searchType);
for (Field field : fields) {
if ((name == null || name.equals(field.getName())) &&
(type == null || type.equals(field.getType()))) {
return field;
}
}
searchType = searchType.getSuperclass();
}
return null;
}
private static Field[] getDeclaredFields(Class> clazz) {
//对类型和字段做了缓存,保存到了declaredFieldsCache中
Field[] result = declaredFieldsCache.get(clazz);
if (result == null) {
result = clazz.getDeclaredFields();
declaredFieldsCache.put(clazz, (result.length == 0 ? NO_FIELDS : result));
}
return result;
5. ReflectionUtils使用场景
最实用的场景就是,当一个接口或者方法针对不同的场景,需要取不同的对象,进行不同的处理。比如发送消息的接口,针对不同的消息类型,可能要处理的数据不一样,有文本消息,有图片消息,有短链,或者菜单栏消息等等。
//通过定义的type字段作区分
//然后找到type对应的属性字段
//找到对应的field对象
Field field = ReflectionUtils.findField(req.getClass(), typeEnum.getField());
//获取数据并赋值
if (Objects.nonNull(field)) {
//设置为可访问
ReflectionUtils.makeAccessible(field);
//根据field的type解析对应的值
Object msgBody = jsonUtils.readValue(bodyStr, field.getType());
//给对象对应的属性字段赋值
ReflectionUtils.setField(field, req, msgBody);
}



