您好,欢迎来到欧得旅游网。
搜索
您的当前位置:首页【Hutool系列】反射工具-ReflectUtil

【Hutool系列】反射工具-ReflectUtil

来源:欧得旅游网

前言

  反射是 Java 中一种强大的机制,可以在运行时动态地获取类的信息并操作类的属性和方法。在 Java 中,通过反射可以获取和设置类的字段、调用类的方法、创建类的实例等。Java的反射机制,可以让语言变得更加灵活,对对象的操作也更加“动态”,因此在某些情况下,反射可以做到事半功倍的效果。本文将介绍如何使用Hutool中的反射工具类来获取获取类信息、操作字段、调用方法、构造对象等常见功能,并提供了相关的代码示例。

一、概述

1.1 工具简介

  Hutool是一个Java工具类库,提供了很多常用的工具类和方法,包括反射操作。通过Hutool,我们可以更加方便地使用反射来获取类的属性值。Hutool针对Java的反射机制做了工具化封装,封装包括获取构造方法、获取字段、获取字段值、获取方法、执行方法(对象方法和静态方法)等。示例如下所示:

// 获取某个类的所有方法
Method[] methods = ReflectUtil.getMethods(PmsBrand.class);
// 获取某个类的指定方法
Method method = ReflectUtil.getMethod(PmsBrand.class, "getId");
// 使用反射来创建对象
PmsBrand pmsBrand = ReflectUtil.newInstance(PmsBrand.class);
// 反射执行对象的方法
ReflectUtil.invoke(pmsBrand,"setId",1);
return CommonResult.success(null,"操作成功!");

1.2 引入依赖

  在使用Hutool工具之前,我们需要将Hutool添加到项目的依赖中。如果使用Maven构建项目,可以在 pom.xml 文件中添加以下依赖:

<!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>${hutool.version}</version>
</dependency>

  Hutool-all 是一个 Hutool 的集成打包产品,由于考虑到“懒人”用户及分不清各个模块作用的用户,“无脑”引入 hutool-all 模块是快速开始和深入应用的最佳方式。如果你想像 SpringBoot 一样引入 Hutool,再由子模块决定用到哪些模块,你可以在父模块中加入:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-bom</artifactId>
            <version>${hutool.version}</version>
            <type>pom</type>
            <!-- 注意这里是import -->
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

  然后再在子模块中就可以引入自己需要的模块了:

<dependencies>
    <dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-core</artifactId>
    </dependency>
</dependencies>

二、基本使用示例

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private String name;
    private Integer age;
    private Boolean gender;
}

2.1 工具类的基本结构

  工具类通常由静态方法组成,并且构造函数设为私有以防止实例化,如下所示。

public class ReflectUtil {
	// 私有构造函数,防止实例化
    public ReflectUtil() {
    
	}
}

2.2 对类的操作

  ReflectionUtil 是一个Java反射工具类,它提供了一些简化反射操作的方法。ReflectionUtil 可以获取类的各种信息,比如类名、类的修饰符、类的父类、实现的接口等,这些信息可以通过调用 ReflectionUtil 的方法来获取。

构造对象

通过反射创建对象,包括使用无参和有参构造方法,如下所示。

@Test
public void constructorTest() {
    // 获取所有构造方法
    Constructor<User>[] constructors = ReflectUtil.getConstructors(User.class);
    for (Constructor<User> constructor : constructors) {
        Console.log("getConstructors->获取构造方法:", constructor);
    }

    // 获取无参构造方法
    Constructor<User> constructor = ReflectUtil.getConstructor(User.class);
    Console.log("getConstructor->获取无参构造方法:", constructor);
    // 获取有参构造方法
    Constructor<User> constructor1 = ReflectUtil.getConstructor(User.class, String.class, Integer.class,Boolean.class);
    Console.log("getConstructor->获取有参构造方法:", constructor1);

    String name = constructor1.getName();
    Console.log("name:{}", name);
    int modifiers = constructor1.getModifiers();
    Console.log("modifiers:{}", modifiers);

}

创建类实例

ReflectionUtil 可以通过反射来创建对象,它提供了一个newInstance 方法,可以根据类名来创建相应的对象。

@Test
public void newInstanceTest() {
    ReflectUtil.newInstance(User.class);
}

2.3 对方法的操作

  通过反射调用类的方法,包括获取方法和执行方法,ReflectionUtil 同样提供了方法来简化方法的调用,一些儿常用方法如下所示。

// 查找指定方法。如果找不到对应的方法则返回null
Method getMethod(Class<?> clazz, boolean ignoreCase, String methodName, Class<?>... paramTypes);

// 按照方法名查找指定方法名的方法,只返回匹配到的第一个方法,如果找不到对应的方法则返回null
Method getMethodIgnoreCase(Class<?> clazz, String methodName, Class<?>... paramTypes);

// 查找指定方法。如果找不到对应的方法则返回null
Method getMethodByName(Class<?> clazz, boolean ignoreCase, String methodName);

// 获得指定类中的方法名
Method[] getMethods(Class<?> beanClass);

// 调用方法。
T invoke(Object obj, Method method, Object... args) throws InvocationTargetRuntimeException, UtilException;

// 执行方法
T invoke(Object obj, String methodName, Object... args) throws UtilException;
T invokeRaw(Object obj, Method method, Object... args) throws InvocationTargetException, IllegalAccessException;

// 执行静态方法
T invokeStatic(Method method, Object... args) throws UtilException;

// 执行方法,执行前要检查给定参数
T invokeWithCheck(Object obj, Method method, Object... args) throws UtilException;

获取类的方法

/**
 * 获取某个类的所有方法
 */
@Test
public void getMethodsTest() {
    Method[] methods = ReflectUtil.getMethods(User.class);
    Arrays.stream(methods).forEach(System.out::println);
}

/**
 * 获取某个类的指定方法
 */
@Test
public void getMethodTest() {
    Method methods = ReflectUtil.getMethod(User.class, "getName");
}

调用方法

  ReflectionUtil 可以通过反射来调用类的方法,它提供了 invokeXXXX 方法,可以根据方法名和参数类型来调用相应的方法。

@Test
public void invokeMethodTest() {
    ReflectUtil.invoke(User.class, "setName", "独泪了无痕");
}

2.4 对属性的操作

  ReflectUtil 也简化了对字段的访问操作,可以通过反射来获取对象的字段值,它提供了一个 getFieldValue 方法,可以根据字段名来获取相应的字段值。除此之外,还可以通过反射来设置对象的字段值,提供了一个 setFieldValue 方法,可以根据字段名来设置相应的字段值。

// 查找指定类中的指定name的字段,也包括父类和Object类的字段,字段不存在则返回null
Field getField(Class<?> beanClass, String name);

// 获取指定类中字段名和字段对应的有序Map,包括其父类中的字段。
// 如果子类与父类中存在同名字段,则这两个字段同时存在,子类字段在前,父类字段在后
Map<String, Field> getFieldMap(Class<?> beanClass);

// 获取字段名,如果存在Alias注解,读取注解的值作为名称
String getFieldName(Field field);

// 获得一个类中所有字段列表,包括其父类中的字段。
// 如果子类与父类中存在同名字段,则这两个字段同时存在,子类字段在前,父类字段在后
Field[] getFields(Class<?> beanClass);

// 获取指定对象所有字段的值
Object[] getFieldsValue(Object obj);

// 获取字段值
Object getFieldValue(Object obj, Field field);
Object getFieldValue(Object obj, String fieldName);

获取类的属性字段

@Test
public void getFieldsTest() {
    User user = new User();
    // 获取实体中所有属性字段
    Field[] fields = ReflectUtil.getFields(user.getClass());
    Arrays.stream(fields).forEach(field -> {
        Console.log("getFields-获取User类的所有字段:", field);
        Console.log("getFieldName->获取字段名:", ReflectUtil.getFieldName(field));
        Console.log("getFieldValue->获取字段值:", ReflectUtil.getFieldValue(new User(), field));
        Console.log("getModifiers->获取字段修饰符:", field.getModifiers());
        Console.log("getType->获取字段类型:", field.getType());
        Console.log("获取属性字段类型:", field.getType().getCanonicalName());
    });
}

获取类的字段值

通过 Hutool 中的 ReflectUtil 类,我们可以获取Java类的字段值,如下所示:

@Test
public void getFieldValueTest() {
    User user = new User();
    user.setName("独泪了无痕");
    user.setAge(30);
    user.setGender(true);
    System.out.println("Name:" + ReflectUtil.getFieldValue(user, "name"));
    System.out.println("Age:" + ReflectUtil.getFieldValue(user, "age"));
    System.out.println("Gender:" + ReflectUtil.getFieldValue(user, "gender"));
}

  在上面的示例中,我们通过 ReflectUtil.getFieldValue() 方法获取了类的字段值。该方法接受两个参数,第一个参数是要获取字段值的对象,第二个参数是字段的名称。

三、总结

  ReflectUtils类通过结合Java反射和Lambda表达式,提供了一种简洁高效的方式来操作对象的字段。它不仅提高了代码的可读性,还通过缓存机制优化了性能。掌握这个工具类的使用,将有助于提升Java开发的灵活性和效率。但使用反射仍然需要谨慎。反射操作可能会破坏封装性、增加性能开销,并可能引发安全问题。因此,在不需要动态访问的情况下,最好避免使用反射。

  Hotool 不仅仅只有这一种工具类,还包含了其他许多工具类。在这里我作为一名Hutool的用户,我感谢Hutool的创作者和维护者们为我们带来如此强大便捷的工具库,希望Hutool功能越来越完善,为我们的开发工作带来更多的便利。同时也祝愿所有开发者没有BUG困扰,能够愉快地编写出高效、功能完善的程序。

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- ovod.cn 版权所有 湘ICP备2023023988号-4

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务