上一篇
通过Java反射机制可动态获取对象属性值,常用Class.getDeclaredFields()遍历字段,或借助BeanUtils等工具类简化操作。
方法1:Java反射机制(原生支持)
反射是Java核心API提供的动态操作类成员的能力,无需第三方库。
import java.lang.reflect.Field;
public class ReflectionExample {
public static void main(String[] args) {
// 示例对象
Person person = new Person("张三", 25);
try {
// 1. 获取Class对象
Class<?> clazz = person.getClass();
// 2. 根据属性名获取Field对象
Field field = clazz.getDeclaredField("name"); // 属性名称为字符串
// 3. 突破私有成员访问限制
field.setAccessible(true);
// 4. 获取属性值
Object value = field.get(person);
System.out.println(value); // 输出: 张三
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
注意事项:
- 安全性:反射可访问私有属性(
setAccessible(true)),需确保符合安全规范。 - 异常处理:必须捕获
NoSuchFieldException(属性不存在)和IllegalAccessException(访问权限异常)。 - 性能:频繁操作时反射效率较低,建议缓存
Field对象。
方法2:Apache Commons BeanUtils(简化操作)
适用于简化反射代码,需添加依赖:

<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.4</version>
</dependency>
代码示例:
import org.apache.commons.beanutils.PropertyUtils;
public class BeanUtilsExample {
public static void main(String[] args) {
Person person = new Person("李四", 30);
try {
// 直接通过属性名字符串获取值
Object name = PropertyUtils.getProperty(person, "name");
System.out.println(name); // 输出: 李四
// 支持嵌套属性(如person.address.city)
} catch (Exception e) {
e.printStackTrace();
}
}
}
优势:

- 支持嵌套属性路径(如
"address.city")。 - 自动处理类型转换和访问权限。
方法3:Spring Framework的BeanWrapper(企业级方案)
Spring容器内置工具,适合Spring项目:
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
public class SpringExample {
public static void main(String[] args) {
Person person = new Person("王五", 40);
BeanWrapper wrapper = new BeanWrapperImpl(person);
// 获取属性值
Object name = wrapper.getPropertyValue("name");
System.out.println(name); // 输出: 王五
// 设置属性值
wrapper.setPropertyValue("age", 45);
System.out.println(person.getAge()); // 输出: 45
}
}
适用场景:

- 已在Spring环境中集成时推荐使用。
- 提供类型安全检查和丰富的元数据操作。
关键注意事项
- 性能优化:
- 反射:缓存
Class和Field对象(如使用Map存储)。 - 避免在循环中频繁调用反射方法。
- 反射:缓存
- 安全性:
- 禁止通过用户输入字符串直接操作属性(易引发安全破绽),应做白名单校验。
- 敏感属性(如密码)避免使用反射暴露。
- 健壮性:
- 检查属性是否存在:
clazz.getDeclaredFields()遍历字段列表。 - 处理
IllegalAccessException,确保权限合规。
- 检查属性是否存在:
方法对比与选择建议
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| Java反射 | 无依赖、原生支持 | 代码冗长、需手动处理异常 | 简单场景或基础库开发 |
| Apache BeanUtils | 简洁易用、支持嵌套属性 | 引入第三方依赖 | 快速开发、非Spring项目 |
| Spring BeanWrapper | 集成Spring生态、功能丰富 | 依赖Spring框架 | Spring应用 |
- 轻量级需求:优先选择原生反射,注意缓存优化。
- 复杂对象操作:使用Apache Commons BeanUtils简化代码。
- Spring项目:直接采用BeanWrapper实现高效集成。
- 安全准则:始终验证输入字符串,避免暴露敏感属性。
引用说明:
- Java反射机制参考Oracle官方文档
- Apache Commons BeanUtils文档见官网
- Spring Framework文档参考Spring.io 遵循Java SE 8+规范,示例代码经过功能验证。
