字段工具-FieldUtil
# 1. 功能概述
FieldUtil 是 Hutool 提供的反射字段工具类,用于处理 Java 反射中的 Field 对象,提供了字段获取、字段赋值、字段信息查询等功能。该工具类简化了 Java 反射中字段操作的复杂性,提供了安全、高效的字段访问方式。
# 2. 核心功能
# 2.1 字段判断
- isOuterClassField(field):判断是否为父类引用字段
# 2.2 字段获取
- hasField(beanClass, name):检查类中是否包含指定名称的字段
- getFieldName(field):获取字段名,支持
@Alias注解 - getDeclaredField(beanClass, name):获取本类定义的指定名称字段(包括非 public)
- getField(beanClass, name):获取类及其父类中指定名称的字段
- getFieldMap(beanClass):获取类中字段名和字段对应的 Map
- getFields(beanClass):获取类及其父类中的所有字段
- getDeclaredFields(beanClass):获取类中声明的所有字段(不包括父类)
- getFieldsDirectly(beanClass, withSuperClassFields):直接获取字段,无缓存
# 2.3 字段值获取
- getFieldValue(obj, fieldName):获取对象指定字段的值
- getStaticFieldValue(field):获取静态字段的值
- getFieldValue(obj, field):获取对象字段的值
- getFieldsValue(obj):获取对象所有字段的值
# 2.4 字段值设置
- setFieldValue(obj, fieldName, value):设置对象指定字段的值
- setStaticFieldValue(field, value):设置静态字段的值
- setFieldValue(obj, field, value):设置对象字段的值,支持自动类型转换
# 3. 方法详解
# 3.1 字段判断
# isOuterClassField(field)
功能:判断是否为父类引用字段
参数:
field:字段对象
返回值:是否为父类引用字段
说明:当字段所在类是对象子类时(对象中定义的非 static 的 class),会自动生成一个以"this$0"为名称的字段,指向父类对象。
示例:
Field field = ...;
boolean isOuter = FieldUtil.isOuterClassField(field);
# 3.2 字段获取
# hasField(beanClass, name)
功能:检查类中是否包含指定名称的字段
参数:
beanClass:被查找字段的类name:字段名
返回值:是否包含字段
示例:
boolean hasNameField = FieldUtil.hasField(User.class, "name");
# getFieldName(field)
功能:获取字段名,支持 @Alias 注解
参数:
field:字段对象
返回值:字段名
示例:
Field field = User.class.getDeclaredField("userName");
String fieldName = FieldUtil.getFieldName(field);
# getDeclaredField(beanClass, name)
功能:获取本类定义的指定名称字段(包括非 public)
参数:
beanClass:Bean 的 Classname:字段名称
返回值:字段对象,未找到则返回 null
示例:
Field privateField = FieldUtil.getDeclaredField(User.class, "privateField");
# getField(beanClass, name)
功能:获取类及其父类中指定名称的字段
参数:
beanClass:被查找字段的类name:字段名
返回值:字段对象,未找到则返回 null
示例:
Field field = FieldUtil.getField(User.class, "name");
# getFieldMap(beanClass)
功能:获取类中字段名和字段对应的 Map
参数:
beanClass:类
返回值:字段名和字段对应的 Map,有序
说明:如果子类与父类中存在同名字段,则父类字段忽略。
示例:
Map<String, Field> fieldMap = FieldUtil.getFieldMap(User.class);
# getFields(beanClass)
功能:获取类及其父类中的所有字段
参数:
beanClass:类
返回值:字段列表
说明:如果子类与父类中存在同名字段,则这两个字段同时存在,子类字段在前,父类字段在后。
示例:
Field[] fields = FieldUtil.getFields(User.class);
# getDeclaredFields(beanClass)
功能:获取类中声明的所有字段(不包括父类)
参数:
beanClass:类
返回值:字段列表
示例:
Field[] declaredFields = FieldUtil.getDeclaredFields(User.class);
# getFieldsDirectly(beanClass, withSuperClassFields)
功能:直接获取字段,无缓存
参数:
beanClass:类withSuperClassFields:是否包括父类的字段列表
返回值:字段列表
示例:
Field[] fields = FieldUtil.getFieldsDirectly(User.class, true);
# 3.3 字段值获取
# getFieldValue(obj, fieldName)
功能:获取对象指定字段的值
参数:
obj:对象,如果是 static 字段,此处为类fieldName:字段名
返回值:字段值
示例:
User user = new User();
Object value = FieldUtil.getFieldValue(user, "name");
# getStaticFieldValue(field)
功能:获取静态字段的值
参数:
field:字段对象
返回值:字段值
示例:
Field staticField = User.class.getDeclaredField("staticField");
Object value = FieldUtil.getStaticFieldValue(staticField);
# getFieldValue(obj, field)
功能:获取对象字段的值
参数:
obj:对象,如果是 static 字段,此参数为 nullfield:字段对象
返回值:字段值
示例:
User user = new User();
Field field = User.class.getDeclaredField("name");
Object value = FieldUtil.getFieldValue(user, field);
# getFieldsValue(obj)
功能:获取对象所有字段的值
参数:
obj:bean 对象,如果是 static 字段,此处为类 class
返回值:字段值数组
示例:
User user = new User();
Object[] values = FieldUtil.getFieldsValue(user);
# 3.4 字段值设置
# setFieldValue(obj, fieldName, value)
功能:设置对象指定字段的值
参数:
obj:对象,static 字段则此处传 ClassfieldName:字段名value:值,值类型必须与字段类型匹配,不会自动转换对象类型
示例:
User user = new User();
FieldUtil.setFieldValue(user, "name", "张三");
# setStaticFieldValue(field, value)
功能:设置静态(static)字段值
参数:
field:字段对象value:值,值类型必须与字段类型匹配,不会自动转换对象类型
示例:
Field staticField = User.class.getDeclaredField("staticField");
FieldUtil.setStaticFieldValue(staticField, "newValue");
# setFieldValue(obj, field, value)
功能:设置对象字段的值,支持自动类型转换
参数:
obj:对象,如果是 static 字段,此参数为 nullfield:字段对象value:值,类型不匹配会自动转换对象类型
示例:
User user = new User();
Field field = User.class.getDeclaredField("age");
FieldUtil.setFieldValue(user, field, "20"); // 自动转换为 int 类型
# 4. 示例代码
# 4.1 基本字段操作
// 创建测试对象
User user = new User();
user.setName("张三");
user.setAge(25);
// 获取字段值
String name = (String) FieldUtil.getFieldValue(user, "name");
int age = (int) FieldUtil.getFieldValue(user, "age");
Console.log("姓名:{}", name); // 输出:姓名:张三
Console.log("年龄:{}", age); // 输出:年龄:25
// 设置字段值
FieldUtil.setFieldValue(user, "name", "李四");
FieldUtil.setFieldValue(user, "age", 30);
Console.log("修改后姓名:{}", user.getName()); // 输出:修改后姓名:李四
Console.log("修改后年龄:{}", user.getAge()); // 输出:修改后年龄:30
# 4.2 私有字段操作
class PrivateUser {
private String privateName = "私有名称";
}
PrivateUser privateUser = new PrivateUser();
// 直接访问私有字段
String privateName = (String) FieldUtil.getFieldValue(privateUser, "privateName");
Console.log("私有字段值:{}", privateName); // 输出:私有字段值:私有名称
// 修改私有字段
FieldUtil.setFieldValue(privateUser, "privateName", "修改后的私有名称");
privateName = (String) FieldUtil.getFieldValue(privateUser, "privateName");
Console.log("修改后私有字段值:{}", privateName); // 输出:修改后私有字段值:修改后的私有名称
# 4.3 字段信息查询
// 获取类的所有字段
Field[] fields = FieldUtil.getFields(User.class);
Console.log("User类的所有字段:");
for (Field field : fields) {
Console.log("字段名:{}", field.getName());
Console.log("字段类型:{}", field.getType());
Console.log("是否为public:{}", Modifier.isPublic(field.getModifiers()));
Console.log("---");
}
// 获取字段映射
Map<String, Field> fieldMap = FieldUtil.getFieldMap(User.class);
Console.log("字段映射:{}", fieldMap.keySet());
# 5. 注意事项
- 性能优化:FieldUtil 使用了弱引用缓存(WeakConcurrentMap)来存储字段信息,提高了字段访问的性能。
- 安全访问:工具类会自动处理字段的可访问性,无需手动调用
setAccessible(true)。 - 异常处理:所有反射异常都会被包装为
HutoolException,统一异常处理。 - 静态字段:处理静态字段时,对象参数应为
null或类对象本身。 - 父类字段:默认情况下,字段获取会包括父类的字段,可通过方法参数控制是否包含父类字段。
- 字段名冲突:当子类与父类存在同名字段时,
getFields()方法会返回两个字段,而getFieldMap()方法会只保留子类字段。
# 6. 最佳实践
- 频繁访问优化:对于频繁访问的字段,建议缓存 Field 对象,减少反射调用的开销。
- 批量操作:对于批量字段操作,使用
getFields()或getFieldMap()获取所有字段后进行遍历操作,比多次调用单个字段方法更高效。 - 类型安全:在获取字段值后,建议进行类型检查或转换,避免类型转换异常。
- 注解支持:利用
getFieldName()方法支持@Alias注解的特性,可以实现字段名的灵活映射。 - 避免过度使用:虽然反射提供了强大的动态能力,但过度使用会影响性能,建议在必要时才使用反射操作。
FieldUtil 工具类为 Java 反射中的字段操作提供了全面的支持,简化了字段获取、赋值和信息查询的复杂性,是 Hutool 反射模块中的核心工具类之一。