微信開發(fā)網(wǎng)站建設(shè)天津網(wǎng)站優(yōu)化
前言
??反射是 Java 中一種強(qiáng)大的機(jī)制,可以在運行時動態(tài)地獲取類的信息并操作類的屬性和方法。在 Java 中,通過反射可以獲取和設(shè)置類的字段、調(diào)用類的方法、創(chuàng)建類的實例等。Java的反射機(jī)制,可以讓語言變得更加靈活,對對象的操作也更加“動態(tài)”,因此在某些情況下,反射可以做到事半功倍的效果。本文將介紹如何使用Hutool中的反射工具類來獲取獲取類信息、操作字段、調(diào)用方法、構(gòu)造對象等常見功能,并提供了相關(guān)的代碼示例。
一、概述
1.1 工具簡介
??Hutool是一個Java工具類庫,提供了很多常用的工具類和方法,包括反射操作。通過Hutool,我們可以更加方便地使用反射來獲取類的屬性值。Hutool針對Java的反射機(jī)制做了工具化封裝,封裝包括獲取構(gòu)造方法、獲取字段、獲取字段值、獲取方法、執(zhí)行方法(對象方法和靜態(tài)方法)等。示例如下所示:
// 獲取某個類的所有方法
Method[] methods = ReflectUtil.getMethods(PmsBrand.class);
// 獲取某個類的指定方法
Method method = ReflectUtil.getMethod(PmsBrand.class, "getId");
// 使用反射來創(chuàng)建對象
PmsBrand pmsBrand = ReflectUtil.newInstance(PmsBrand.class);
// 反射執(zhí)行對象的方法
ReflectUtil.invoke(pmsBrand,"setId",1);
return CommonResult.success(null,"操作成功!");
1.2 引入依賴
??在使用Hutool工具之前,我們需要將Hutool添加到項目的依賴中。如果使用Maven構(gòu)建項目,可以在 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 的集成打包產(chǎn)品,由于考慮到“懶人”用戶及分不清各個模塊作用的用戶,“無腦”引入 hutool-all 模塊是快速開始和深入應(yīng)用的最佳方式。如果你想像 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 工具類的基本結(jié)構(gòu)
??工具類通常由靜態(tài)方法組成,并且構(gòu)造函數(shù)設(shè)為私有以防止實例化,如下所示。
public class ReflectUtil {// 私有構(gòu)造函數(shù),防止實例化public ReflectUtil() {}
}
2.2 對類的操作
??ReflectionUtil 是一個Java反射工具類,它提供了一些簡化反射操作的方法。ReflectionUtil 可以獲取類的各種信息,比如類名、類的修飾符、類的父類、實現(xiàn)的接口等,這些信息可以通過調(diào)用 ReflectionUtil 的方法來獲取。
構(gòu)造對象
通過反射創(chuàng)建對象,包括使用無參和有參構(gòu)造方法,如下所示。
@Test
public void constructorTest() {// 獲取所有構(gòu)造方法Constructor<User>[] constructors = ReflectUtil.getConstructors(User.class);for (Constructor<User> constructor : constructors) {Console.log("getConstructors->獲取構(gòu)造方法:", constructor);}// 獲取無參構(gòu)造方法Constructor<User> constructor = ReflectUtil.getConstructor(User.class);Console.log("getConstructor->獲取無參構(gòu)造方法:", constructor);// 獲取有參構(gòu)造方法Constructor<User> constructor1 = ReflectUtil.getConstructor(User.class, String.class, Integer.class,Boolean.class);Console.log("getConstructor->獲取有參構(gòu)造方法:", constructor1);String name = constructor1.getName();Console.log("name:{}", name);int modifiers = constructor1.getModifiers();Console.log("modifiers:{}", modifiers);}
創(chuàng)建類實例
ReflectionUtil 可以通過反射來創(chuàng)建對象,它提供了一個newInstance 方法,可以根據(jù)類名來創(chuàng)建相應(yīng)的對象。
@Test
public void newInstanceTest() {ReflectUtil.newInstance(User.class);
}
2.3 對方法的操作
??通過反射調(diào)用類的方法,包括獲取方法和執(zhí)行方法,ReflectionUtil 同樣提供了方法來簡化方法的調(diào)用,一些兒常用方法如下所示。
// 查找指定方法。如果找不到對應(yīng)的方法則返回null
Method getMethod(Class<?> clazz, boolean ignoreCase, String methodName, Class<?>... paramTypes);// 按照方法名查找指定方法名的方法,只返回匹配到的第一個方法,如果找不到對應(yīng)的方法則返回null
Method getMethodIgnoreCase(Class<?> clazz, String methodName, Class<?>... paramTypes);// 查找指定方法。如果找不到對應(yīng)的方法則返回null
Method getMethodByName(Class<?> clazz, boolean ignoreCase, String methodName);// 獲得指定類中的方法名
Method[] getMethods(Class<?> beanClass);// 調(diào)用方法。
T invoke(Object obj, Method method, Object... args) throws InvocationTargetRuntimeException, UtilException;// 執(zhí)行方法
T invoke(Object obj, String methodName, Object... args) throws UtilException;
T invokeRaw(Object obj, Method method, Object... args) throws InvocationTargetException, IllegalAccessException;// 執(zhí)行靜態(tài)方法
T invokeStatic(Method method, Object... args) throws UtilException;// 執(zhí)行方法,執(zhí)行前要檢查給定參數(shù)
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");
}
調(diào)用方法
??ReflectionUtil 可以通過反射來調(diào)用類的方法,它提供了 invokeXXXX
方法,可以根據(jù)方法名和參數(shù)類型來調(diào)用相應(yīng)的方法。
@Test
public void invokeMethodTest() {ReflectUtil.invoke(User.class, "setName", "獨淚了無痕");
}
2.4 對屬性的操作
??ReflectUtil 也簡化了對字段的訪問操作,可以通過反射來獲取對象的字段值,它提供了一個 getFieldValue
方法,可以根據(jù)字段名來獲取相應(yīng)的字段值。除此之外,還可以通過反射來設(shè)置對象的字段值,提供了一個 setFieldValue
方法,可以根據(jù)字段名來設(shè)置相應(yīng)的字段值。
// 查找指定類中的指定name的字段,也包括父類和Object類的字段,字段不存在則返回null
Field getField(Class<?> beanClass, String name);// 獲取指定類中字段名和字段對應(yīng)的有序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()
方法獲取了類的字段值。該方法接受兩個參數(shù),第一個參數(shù)是要獲取字段值的對象,第二個參數(shù)是字段的名稱。
三、總結(jié)
??ReflectUtils類通過結(jié)合Java反射和Lambda表達(dá)式,提供了一種簡潔高效的方式來操作對象的字段。它不僅提高了代碼的可讀性,還通過緩存機(jī)制優(yōu)化了性能。掌握這個工具類的使用,將有助于提升Java開發(fā)的靈活性和效率。但使用反射仍然需要謹(jǐn)慎。反射操作可能會破壞封裝性、增加性能開銷,并可能引發(fā)安全問題。因此,在不需要動態(tài)訪問的情況下,最好避免使用反射。
??Hotool 不僅僅只有這一種工具類,還包含了其他許多工具類。在這里我作為一名Hutool的用戶,我感謝Hutool的創(chuàng)作者和維護(hù)者們?yōu)槲覀儙砣绱藦?qiáng)大便捷的工具庫,希望Hutool功能越來越完善,為我們的開發(fā)工作帶來更多的便利。同時也祝愿所有開發(fā)者沒有BUG困擾,能夠愉快地編寫出高效、功能完善的程序。