反射(二)ReflectionUtils

一、介绍

1、简介

org.springframework.util.ReflectionUtils 是 Spring 框架提供的一个反射工具类,它封装了 Java 反射 API 的一些常用操作,使得我们能够更加方便、简洁地使用反射功能。

虽然 ReflectionUtils 提供了很多便捷的方法,但使用反射仍然需要谨慎。反射操作可能会破坏封装性、增加性能开销,并可能引发安全问题。因此,在不需要动态访问的情况下,最好避免使用反射。

二、API

1、获取 Class 对象

ReflectionUtils 提供了多种获取 Class 对象的方法,如:

(1)findClass(String name): 根据类名获取 Class 对象,与 Class.forName(String) 类似,但会缓存已经加载过的类。
(2)getClass(Object obj): 获取对象的运行时类,与 obj.getClass() 等效。
(3)getUserClass(Object obj): 如果对象是代理对象,则获取其背后的实际类(即目标类),否则与 getClass(Object) 相同。

2、访问字段(Field)

(1)findField(Class<?> clazz, String name): 在给定的类及其父类中查找具有指定名称的字段。

import org.springframework.util.ReflectionUtils;

public class Person {
    private String name;

    public Person(String name) {
        this.name = name;
    }

    // 省略其他方法...
}

public class ReflectionExample {
    public static void main(String[] args) {
        Person person = new Person("zs");
        String fieldName = "name";

        // 使用 ReflectionUtils 获取私有字段的值
        String nameValue = (String) ReflectionUtils.getFieldValue(person, fieldName);
        System.out.println("Name value: " + nameValue); // 输出: Name value: zs
    }
}

(2)findField(Class<?> clazz, String name, Class<?> type): 根据名称和类型查找字段。
(3)getField(Field field): 获取可访问的字段对象,如果字段是私有的,会设置其为可访问。

(4)setField(Object obj, String name, Object value): 设置指定对象的字段值。

public class ReflectionExample {
    public static void main(String[] args) {
        Person person = new Person("John Doe");
        String fieldName = "name";
        String newValue = "zs";

        // 使用 ReflectionUtils 设置私有字段的值
        ReflectionUtils.setField(person, fieldName, newValue);

        // 再次获取并验证字段值已更改
        String updatedValue = (String) ReflectionUtils.getFieldValue(person, fieldName);
        System.out.println("Updated name value: " + updatedValue); // 输出: Updated name value: zs
    }
}

(5)getFieldValue(Object obj, String name): 获取指定对象的字段值。

3、调用方法(Method)

(1)findMethod(Class<?> clazz, String name, Class<?>... paramTypes):

       查找具有指定名称和参数类型的方法。

Method method = ReflectionUtils.findMethod(aClass, methodName);

(2)invokeMethod(Method method, Object target): 调用无参数方法。

Object[] parameters = new Object[parameterTypes.length];
result = ReflectionUtils.invokeMethod(preCheckMethod, null, parameters);


(3)invokeMethod(Method method, Object target, Object... args): 调用带参数的方法。
(4)invokeJdbcMethod(Method method, Object target, Object... args):

      专为 JDBC 方法设计的调用,处理 SQL 异常。
(5)makeAccessible(Method method): 确保方法可以访问,即使它是私有的。

4、构造函数和实例化

(1)getConstructorIfAvailable(Class<?> clazz, Class<?>... paramTypes):

   尝试获取指定参数类型的构造函数,如果找不到则返回 null。
(2)instantiateClass(Constructor<?> ctor, Object... args): 使用指定的构造函数和参数实例化类。

(3)newInstance(Class<?> clazz, Object... args): 简化版的实例化方法,它内部会查找合适的构造函数并调用 instantiateClass。

5、其他实用方法

(1)isAssignable(Class<?> lhsType, Class<?> rhsType): 判断一个类是否可以赋值给另一个类(考虑继承关系)。
(2)doesMethodDeclareException(Method method, Class<?> exceptionType):

  检查方法是否声明了指定类型的异常。

import org.springframework.util.ReflectionUtils;
import java.io.IOException;

public class ExampleWithException {
    public void methodThatThrows() throws IOException {
        // ... 方法实现 ...
    }
}

public class ReflectionExample {
    public static void main(String[] args) {
        boolean declaresException = ReflectionUtils.doesMethodDeclareException(
                ReflectionUtils.findMethod(ExampleWithException.class, "methodThatThrows"), IOException.class);
        System.out.println("Declares IOException: " + declaresException); // 输出: Declares IOException: true
    }
}

(3)getUniqueDeclaredMethods(Class<?> leafClass): 获取类中声明的所有方法,包括继承的方法,但排除重写的方法,确保每个方法只出现一次。
(4)getAllDeclaredMethods(Class<?> leafClass): 获取类中声明的所有方法,包括继承的方法,但不排除重写的方法。
(5)getDeclaredMethods(Class<?> clazz): 获取类中直接声明的所有方法,不包括继承的方法。
(6)getDeclaredFields(Class<?> clazz): 获取类中直接声明的所有字段。

Method method = ReflectionUtils.findMethod(aClass, methodName);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

w_t_y_y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值