本文目录导读:

我来为您提供一个Java反射赋值的完整案例。
基础反射赋值示例
实体类
public class User {
private Long id;
private String name;
private Integer age;
private String email;
// 无参构造
public User() {}
// getter和setter方法
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Integer getAge() { return age; }
public void setAge(Integer age) { this.age = age; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
@Override
public String toString() {
return "User{id=" + id + ", name='" + name + "', age=" + age + ", email='" + email + "'}";
}
}
反射赋值工具类
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
public class ReflectUtil {
/**
* 通过setter方法反射赋值
*/
public static <T> T setFieldBySetter(T object, String fieldName, Object value) {
try {
// 获取对象的Class
Class<?> clazz = object.getClass();
// 构建setter方法名
String setterName = "set" + fieldName.substring(0, 1).toUpperCase()
+ fieldName.substring(1);
// 获取setter方法
Method setter = clazz.getMethod(setterName, value.getClass());
// 调用setter方法
setter.invoke(object, value);
} catch (Exception e) {
e.printStackTrace();
}
return object;
}
/**
* 通过Field直接赋值(忽略访问修饰符)
*/
public static <T> T setFieldByField(T object, String fieldName, Object value) {
try {
// 获取对象的Class
Class<?> clazz = object.getClass();
// 获取Field
Field field = clazz.getDeclaredField(fieldName);
// 设置可访问(private字段也可访问)
field.setAccessible(true);
// 赋值
field.set(object, value);
} catch (Exception e) {
e.printStackTrace();
}
return object;
}
/**
* 使用Map批量赋值
*/
public static <T> T setFieldsByMap(T object, Map<String, Object> fieldMap) {
for (Map.Entry<String, Object> entry : fieldMap.entrySet()) {
setFieldBySetter(object, entry.getKey(), entry.getValue());
}
return object;
}
}
测试类
public class ReflectTest {
public static void main(String[] args) {
// 方法1:使用setter反射赋值
testSetterReflect();
System.out.println("========================");
// 方法2:使用Field直接赋值
testFieldReflect();
System.out.println("========================");
// 方法3:使用Map批量赋值
testMapReflect();
}
// 方法1:通过setter反射赋值
private static void testSetterReflect() {
System.out.println("=== 通过setter反射赋值 ===");
User user = new User();
// 调用工具类赋值
ReflectUtil.setFieldBySetter(user, "id", 1L);
ReflectUtil.setFieldBySetter(user, "name", "张三");
ReflectUtil.setFieldBySetter(user, "age", 25);
ReflectUtil.setFieldBySetter(user, "email", "zhangsan@example.com");
System.out.println("设置后的对象:" + user);
}
// 方法2:通过Field直接赋值
private static void testFieldReflect() {
System.out.println("=== 通过Field直接赋值 ===");
User user = new User();
// 调用工具类赋值
try {
ReflectUtil.setFieldByField(user, "id", 2L);
ReflectUtil.setFieldByField(user, "name", "李四");
ReflectUtil.setFieldByField(user, "age", 30);
ReflectUtil.setFieldByField(user, "email", "lisi@example.com");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("设置后的对象:" + user);
}
// 方法3:使用Map批量赋值
private static void testMapReflect() {
System.out.println("=== 使用Map批量赋值 ===");
User user = new User();
// 准备数据
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("id", 3L);
dataMap.put("name", "王五");
dataMap.put("age", 28);
dataMap.put("email", "wangwu@example.com");
// 批量赋值
ReflectUtil.setFieldsByMap(user, dataMap);
System.out.println("设置后的对象:" + user);
}
}
高级应用:对象属性拷贝
import java.lang.reflect.Field;
public class BeanCopyUtil {
/**
* 对象属性拷贝(支持不同类型间的相同属性名拷贝)
*/
public static <T> T copyProperties(Object source, Class<T> targetClass) {
try {
// 创建目标对象实例
T target = targetClass.getDeclaredConstructor().newInstance();
// 获取源对象的所有字段
Field[] sourceFields = source.getClass().getDeclaredFields();
for (Field sourceField : sourceFields) {
// 设置源对象字段可访问
sourceField.setAccessible(true);
try {
// 获取目标对象中同名字段
Field targetField = targetClass.getDeclaredField(sourceField.getName());
targetField.setAccessible(true);
// 获取源对象字段值
Object value = sourceField.get(source);
// 赋值给目标对象
targetField.set(target, value);
} catch (NoSuchFieldException e) {
// 目标对象没有该字段,跳过
continue;
}
}
return target;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
测试对象属性拷贝
public class BeanCopyTest {
public static void main(String[] args) {
// 创建源对象
User user = new User();
user.setId(1L);
user.setName("测试用户");
user.setAge(25);
user.setEmail("test@example.com");
// 拷贝到另一个User对象
User userCopy = BeanCopyUtil.copyProperties(user, User.class);
System.out.println("源对象:" + user);
System.out.println("拷贝对象:" + userCopy);
}
}
性能优化:缓存反射元数据
import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;
public class ReflectCacheUtil {
// 缓存Method对象,提高性能
private static final ConcurrentHashMap<String, Method> METHOD_CACHE = new ConcurrentHashMap<>();
public static <T> T setFieldCached(T object, String fieldName, Object value) {
try {
Class<?> clazz = object.getClass();
// 构建缓存key
String cacheKey = clazz.getName() + "." + fieldName;
// 从缓存获取或创建setter方法
Method setter = METHOD_CACHE.computeIfAbsent(cacheKey, key -> {
try {
String setterName = "set" + fieldName.substring(0, 1).toUpperCase()
+ fieldName.substring(1);
return clazz.getMethod(setterName, value.getClass());
} catch (NoSuchMethodException e) {
throw new RuntimeException("找不到setter方法: " + key, e);
}
});
// 调用setter方法
setter.invoke(object, value);
} catch (Exception e) {
e.printStackTrace();
}
return object;
}
}
运行结果
=== 通过setter反射赋值 ===
设置后的对象:User{id=1, name='张三', age=25, email='zhangsan@example.com'}
========================
=== 通过Field直接赋值 ===
设置后的对象:User{id=2, name='李四', age=30, email='lisi@example.com'}
========================
=== 使用Map批量赋值 ===
设置后的对象:User{id=3, name='王五', age=28, email='wangwu@example.com'}
注意事项
- 访问权限:使用
setAccessible(true)可以访问私有字段,但需要注意安全性 - 类型匹配:反射赋值时需要注意数据类型匹配
- 性能问题:反射操作相对较慢,可考虑缓存Method/Field对象
- 异常处理:反射操作会抛出多种异常,需要妥善处理
- JDK版本:JDK 17+可能需要添加
--add-opens参数
这个案例展示了Java反射赋值的基本用法和高级应用,可以根据实际需求选择适合的赋值方式。