Redian新闻
>
玩转 ReflectionUtils 工具类,离大佬又近一步

玩转 ReflectionUtils 工具类,离大佬又近一步

公众号新闻

ReflectionUtils是Spring框架中的反射工具类,它提供了一系列静态方法,可以方便地进行类、对象、方法、字段等反射操作。

  1. shallowCopyFieldState(final Object src, final Object dest)

    将源对象的属性值浅拷贝到目标对象中。

    该方法会遍历源对象的所有可读属性,并将其值拷贝到目标对象的对应属性中。

    拷贝的方式是通过直接赋值来实现的,因此是浅拷贝,即拷贝的是属性的引用而不是属性的副本。

    Person source = new Person();
    source.setName("John");
    source.setAge(25);
    PersonVO target = new PersonVO();
    // 浅拷贝
    ReflectionUtils.shallowCopyFieldState(source, target);        
    System.out.println("Name: " + target.getName());
    System.out.println("Age: " + target.getAge());

    运行结果:

    Name: John
    Age: 25
  2. handleReflectionException(Exception ex)

    用于处理反射操作中可能抛出的异常。

    它接受一个Exception类型的参数ex,表示要处理的异常。

    Person example = new Person();
    try {
        Method method = Person.class.getMethod("nonExistingMethod");
        ReflectionUtils.invokeMethod(method, example);
    catch (Exception ex) {
        // 处理反射操作中的异常
        ReflectionUtils.handleReflectionException(ex);
    }

    运行结果:

    Exception in thread "main" java.lang.IllegalStateException: Method not found: com.cloudfish.test.Person.nonExistingMethod()
        at org.springframework.util.ReflectionUtils.handleReflectionException(ReflectionUtils.java:109)
        at com.cloudfish.test.ReflectionUtilsTest.main(ReflectionUtilsTest.java:26)

    在示例中,我们调用了一个不存在的方法,固抛异常了。

  3. handleInvocationTargetException(InvocationTargetException ex)

    处理给定的调用目标异常,InvocationTargetException是Java反射中的一个异常类,它表示在调用方法时发生了异常。

    通常情况下,我们可以使用getCause()方法获取原始的异常对象。

  4. rethrowRuntimeException(Throwable ex)

    重新抛出一个运行时异常。

  5. rethrowException(Throwable ex)

    重新抛出一个异常,重新抛出的异常分为三种类型:

    运行时异常RuntimeException、Error、UndeclaredThrowableException。

  6. ReflectionUtils.accessibleConstructor(Classclazz, Class<?>... parameterTypes)

    用于获取指定类的可访问构造函数。

    try {
        Constructor<Person> constructor = ReflectionUtils.accessibleConstructor(Person.classString.classint.class);
        Person example = constructor.newInstance("John Doe"25);
        System.out.println("Name: " + example.getName());
        System.out.println("Age: " + example.getAge());
    catch (Exception ex) {
        ex.printStackTrace();
    }

    运行结果:

    Name: John Doe
    Age: 25
  7. Method findMethod(Class<?> clazz, String name)

    获取指定类的指定方法。

    Method getNameMethod = ReflectionUtils.findMethod(Person.class, "getName");
    System.out.println("getName method: " + getNameMethod);

    运行结果:

    setName method: public java.lang.String com.cloudfish.test.Person.getName()

    注意:该方法只能获取没有参数的方法。

  8. findMethod(Class clazz, String name, @Nullable Class... paramTypes)

    获取指定类的指定方法,该方法还有一个或多个参数类型。

    Method setNameMethod = ReflectionUtils.findMethod(Person.class, "setName", String.class);
    System.out.println("setName method: " + setNameMethod);

    运行结果:

    setName method: public void com.cloudfish.test.Person.setName(java.lang.String)
  9. invokeMethod(Method method, @Nullable Object target)

    用于调用指定方法,并传入目标对象(可选)。

    Method setNameMethod = ReflectionUtils.findMethod(Person.class, "setName", String.class);
    System.out.println("setName method: " + setNameMethod);        

    Person example = new Person();
    // 设置访问权限才可访问
    setNameMethod.setAccessible(true);
    ReflectionUtils.invokeMethod(setNameMethod, example, "eeefdfdfd");          
    System.out.println(example.getName());

    运行结果:

    setName method: public void com.cloudfish.test.Person.setName(java.lang.String)
    eeefdfdfd
  10. declaresException(Method method, Class<?> exceptionType)

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

    Method method = ReflectionUtils.findMethod(Person.class, "getName");
    boolean declaresIOException = ReflectionUtils.declaresException(method, IOException.class);
    System.out.println("Declares IOException: " + declaresIOException);

    boolean declaresNullPointerException = ReflectionUtils.declaresException(method, NullPointerException.class);
    System.out.println("Declares NullPointerException: " + declaresNullPointerException);

    运行结果:

    Declares IOException: false
    Declares NullPointerException: false
  11. doWithLocalMethods(Class<?> clazz, MethodCallback mc)

    用于迭代指定类的所有本地方法,并对每个方法执行回调操作。

    ReflectionUtils.doWithLocalMethods(Person.classnew PersonCallback());

    回调类:

    // 需要实现MethodCallback 方法
    class PersonCallback implements MethodCallback {
        @Override
        public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
            System.out.println("Method name: " + method.getName());
        }
    }

    运行结果:

    Method name: hashCode
    Method name: getAddress
    Method name: getName
    Method name: setName
    Method name: setAddress
    Method name: getAge
    Method name: setAge

    打印了person中所有的方法。

  12. doWithMethods(Class<?> clazz, MethodCallback mc)

    用于迭代指定类的所有方法,并对每个方法执行回调操作。

    ReflectionUtils.doWithMethods(Person.classnew PersonCallback());

    运行结果:

    Method name: hashCode
    Method name: getAddress
    Method name: getName
    Method name: setName
    Method name: setAge
    Method name: getAge
    Method name: setAddress
    Method name: finalize
    Method name: wait
    Method name: wait
    Method name: wait
    Method name: equals
    Method name: toString
    Method name: hashCode
    Method name: getClass
    Method name: clone
    Method name: notify
    Method name: notifyAll
    Method name: registerNatives
  13. doWithMethods(Class<?> clazz, MethodCallback mc, @Nullable MethodFilter mf)

    用于迭代指定类的所有方法,并对每个方法执行回调操作。

    ReflectionUtils.doWithMethods(Person.classnew PersonCallback(), new PersonMethodFilter());

    // 需要实现MethodFilter接口
    class PersonMethodFilter implements MethodFilter {

        @Override
        public boolean matches(Method method) {
            return Modifier.isPublic(method.getModifiers());
        }    
    }

    运行结果:

    Method name: hashCode
    Method name: getAddress
    Method name: getName
    Method name: setName
    Method name: setAge
    Method name: setAddress
    Method name: getAge
    Method name: wait
    Method name: wait
    Method name: wait
    Method name: equals
    Method name: toString
    Method name: hashCode
    Method name: getClass
    Method name: notify
    Method name: notifyAll
  14. getAllDeclaredMethods(Class<?> leafClass)

    用于获取指定类及其所有父类中声明的所有方法。

    Class<?> leafClass = PersonVO.class;
    Method[] methods = ReflectionUtils.getAllDeclaredMethods(leafClass);
    for (Method method : methods) {
       System.out.println("Method name: " + method.getName());
    }

    运行结果:

    Method name: getHobbies
    Method name: setHobbies
    Method name: hashCode
    Method name: getAddress
    Method name: getName
    Method name: setName
    Method name: setAddress
    Method name: getAge
    Method name: setAge
    Method name: finalize
    Method name: wait
    Method name: wait
    Method name: wait
    Method name: equals
    Method name: toString
    Method name: hashCode
    Method name: getClass
    Method name: clone
    Method name: notify
    Method name: notifyAll
    Method name: registerNatives
  15. getUniqueDeclaredMethods(Class<?> leafClass)

    用于获取指定类及其所有父类中声明的所有唯一方法。

    Class<?> leafClass = PersonVO.class;
    Method[] methods = ReflectionUtils.getUniqueDeclaredMethods(leafClass);
    for (Method method : methods) {
        System.out.println("Method name: " + method.getName());
    }

    运行结果:

    Method name: getHobbies
    Method name: setHobbies
    Method name: hashCode
    Method name: getAddress
    Method name: getName
    Method name: setName
    Method name: setAge
    Method name: getAge
    Method name: setAddress
    Method name: finalize
    Method name: wait
    Method name: wait
    Method name: wait
    Method name: equals
    Method name: toString
    Method name: getClass
    Method name: clone
    Method name: notify
    Method name: notifyAll
    Method name: registerNatives
  16. isEqualsMethod(@Nullable Method method)

    用于判断给定的方法是否是equals方法。

    try {
        Class<?> clazz = PersonVO.class;
        Method method = clazz.getMethod("equals", Object.class);
        boolean isEquals = ReflectionUtils.isEqualsMethod(method);
        System.out.println("Is equals method: " + isEquals);
    catch (NoSuchMethodException | SecurityException e) {
        e.printStackTrace();
    }

    运行结果:

    Is equals method: true
  17. isHashCodeMethod(@Nullable Method method)

    用于判断给定的方法是否是hashCode方法。

  18. isToStringMethod(@Nullable Method method)

    用于判断给定的方法是否是toString方法。

  19. isObjectMethod(@Nullable Method method)

    用于判断给定的方法是否是Object类中的方法。

    try {
        Class<?> clazz = PersonVO.class;
        Method method = clazz.getMethod("getName");    
        boolean isObjectMethod = ReflectionUtils.isObjectMethod(method);
        System.out.println("Is Object method: " + isObjectMethod);
    catch (NoSuchMethodException | SecurityException e) {
        e.printStackTrace();
    }

    运行结果:

    Is Object method: false
  20. isCglibRenamedMethod(Method renamedMethod)

    用于判断给定的方法是否是Cglib的类中的renamed方法。

  21. findField(Class<?> clazz, String name)

    用于在给定的类及其父类中查找指定名称的字段。

    Class<?> clazz = PersonVO.class;
    Field field = ReflectionUtils.findField(clazz, "name");
    System.out.println("Field name: " + field.getName());

    运行结果:

    Field name: name
  22. findField(Class clazz, @Nullable String name, @Nullable Class type)

    用于在给定的类及其父类中查找指定名称、类型的字段。

  23. setField(Field field, @Nullable Object target, @Nullable Object value)

    用于设置指定字段的值。

    try {
        Person myObject = new Person();
        Field field = Person.class.getDeclaredField("name");
        // 设置为可以访问
        field.setAccessible(true);
        ReflectionUtils.setField(field, myObject, "Hello, World!");
        System.out.println("Field value: " + myObject.getName());
    catch (NoSuchFieldException | SecurityException e) {
        e.printStackTrace();
    }

    运行结果:

    Field value: Hello, World!
  24. getField(Field field, @Nullable Object target)

    用于获取指定字段的值。

    try {
        Person myObject = new Person("aaaa",10);
        Field field = Person.class.getDeclaredField("name");
        field.setAccessible(true);
        Object value = ReflectionUtils.getField(field, myObject);
        System.out.println("Field value: " + value);
    catch (NoSuchFieldException | SecurityException e) {
        e.printStackTrace();
    }

    运行结果:

    Field value: aaaa
  25. doWithLocalFields(Class<?> clazz, FieldCallback fc)

    用于对指定类的本地字段(即不包括父类的字段)进行操作。

  26. 微信搜索公众号:架构师指南,回复:架构师 领取资料 。

    Class<?> clazz = PersonVO.class;
    MyFieldCallback fieldCallback = new MyFieldCallback();
    ReflectionUtils.doWithLocalFields(clazz, fieldCallback);
    //FieldCallback 类
    class MyFieldCallback implements FieldCallback {
      @Override
      public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
        System.out.println("Field name: " + field.getName());
        System.out.println("Field type: " + field.getType());
      }
    }

    运行结果:

    Field name: hobbies
    Field type: interface java.util.List
  27. doWithFields(Class<?> clazz, FieldCallback fc)

    用于对指定类的字段(包括父类的字段)进行操作。

    Class<?> clazz = PersonVO.class;
    MyFieldCallback fieldCallback = new MyFieldCallback();
    ReflectionUtils.doWithFields(clazz, fieldCallback);

    运行结果:

    Field name: hobbies
    Field type: interface java.util.List
    Field name: name
    Field type: class java.lang.String
    Field name: age
    Field type: int
    Field name: address
    Field type: class java.lang.String
  28. doWithFields(Class<?> clazz, FieldCallback fc, @Nullable FieldFilter ff)

    用于对指定类的符合条件的字段进行操作。

    Person myObject = new Person();
    // 使用doWithFields方法对字段进行操作
    ReflectionUtils.doWithFields(Person.classnew FieldCallback() {
        @Override
        public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
            // 在这里可以对每个字段进行自定义操作
            field.setAccessible(true); // 设置字段可访问,因为字段是私有的
            Object value = field.get(myObject); // 获取字段的值
            System.out.println("Field name: " + field.getName());
            System.out.println("Field type: " + field.getType());
            System.out.println("Field value: " + value);
        }
    }, new FieldFilter() {
        @Override
        public boolean matches(Field field) {
            // 在这里可以定义过滤条件,只处理满足条件的字段
            return field.getType() == String.class// 只处理类型为String的字段
        }
    });

    使用匿名内部类实现了FieldCallback接口,并在doWith方法中定义了对每个字段的操作。

    在doWith方法中,我们首先将字段设置为可访问状态,然后使用field.get(myObject)方法获取字段的值,并打印字段的名称、类型和值。

    同时,我们还使用匿名内部类实现了FieldFilter接口,并在matches方法中定义了过滤条件。

    在这个示例中,我们只处理类型为String的字段。

    运行结果:

    Field name: name
    Field type: class java.lang.String
    Field value: null
    Field name: address
    Field type: class java.lang.String
    Field value: null
  29. isPublicStaticFinal(Field field)

    用于判断一个字段是否是public、static和final修饰的。

    Field[] fields = Person.class.getDeclaredFields();
    for (Field field : fields) {
        if (ReflectionUtils.isPublicStaticFinal(field)) {
            System.out.println(field.getName() + " is public, static, and final.");
        }
    }

    由于在person对象中,并没有这样的字段,所以没有打印结果。

最后总结一下,ReflectionUtils工具类的作用:

  • 获取类的信息:ReflectionUtils可以通过类的全限定名获取对应的Class对象,进而获取类的各种信息,如类名、包名、父类、接口等。

  • 创建对象:ReflectionUtils可以通过Class对象创建实例,即通过反射实现动态创建对象的功能。

  • 调用方法:ReflectionUtils可以通过Method对象调用类的方法,包括无参方法和有参方法,可以通过方法名和参数类型来定位方法。

  • 访问字段:ReflectionUtils可以通过Field对象访问类的字段,包括获取字段值和设置字段值。

  • 调用构造方法:ReflectionUtils可以通过Constructor对象调用类的构造方法,包括无参构造方法和有参构造方法

往期推荐:


再见,Navicat!!
警报炸锅,FastJson 又立功了。。
高德导航红绿灯为啥能读秒?
为什么 List 原生排序比 stream() 流效率更高?



微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
公安部新闻传媒中心揭牌众议院版本法案未通过 离政府关门又近一步AmEx refer 功能突然消失现象及解决方案【更新:大部分卡恢复refer了,但Gold/BCE又不行了】Power Fantasies: The Truth About Chinese ‘Chiefs’ in West AfricaLinux 桌面上的 Firefox 面临着大问题 | Linux 中国吃瓜!她甩了硅谷大佬又嫁富豪, 还和马斯克有关??金刚石半导体,又近了一步Cloudflare 推出免费的隐私保护工具 Turnstile,替代传统 CAPTCHAnǚ hóng?nǚ gōngWarehouse:管理 Flatpak 应用的强大工具 | Linux 中国赵晓光最新发声!资本市场或迎超预期支持!中国民航局发布重磅数据!92岁传媒大佬又恋爱了,啥情况?流感mRNA疫苗上市又近一步,呼吸道“多合一”疫苗也不远了木心与陈丹青网传汪峰章子怡离婚的原因,离大谱。。。Charging Your Electric Car is Becoming More Expensive in ChinaX 推出招聘功能对标 LinkedIn,马斯克的超级应用又近了一步 | Hunt Good 周报大模型落地的故事,离「千行百业」又近了一点Rescue Teams Struggle to Reach Isolated Areas in Flood-Hit Hebei#英语学习#Restrain, Refrain, and Restrict有什么区别?看看你能答对这道题吗?体验丨不瞒你说,我在数码港上班,离香港最有钱的豪宅又近了一步!AmEx Refer Jail (AmEx refer 功能突然消失)现象及解决方案【更新:恢复了!】Ex-Soldier Sleeps in Cave for 22 Years to Protect Song Treasures大隐隐于市!越南一家人在San Jose开的小店全是越南客人——Phở Cường 2我不懂这精神内核和诡异画风PS+AI生图一步完成,效果惊人!Adobe Firefly 2重磅更新:模型全面升级,矢量图完美支持那曲久远的音乐Hiring | B.A.A. MANAGER OF EXECUTIVE SUPPORT & PROJECTSIEEE-IDPC 资源快讯 | EDA(Electronic Design Automation)亩产1186公斤!距离袁爷爷的目标又近了一步加州离通高铁又近了一步QQ 用 Electron 重构后,终实现 Linux、macOS、Windows 三端架构统一!Java导入、导出excel保姆级教程(附封装好的工具类)Meta Connect 2023定档;苹果、Adobe、皮克斯、Nvidia、Autodesk组建OpenUSD联盟别再自己瞎写工具类了,SpringBoot内置工具类应有尽有,建议收藏!!20200629 《天涯客》定妆照发布
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。