java可通过反射实现通用浅拷贝工具:遍历源对象非static/final字段,用get/set完成赋值;需处理基本类型null值、忽略特定字段,并确保目标对象已实例化且类型兼容。

Java 可以通过反射机制实现一个通用的对象浅拷贝工具,核心思路是:遍历源对象的所有可读字段(包括私有字段),读取其值,再设置到目标对象的对应字段上。注意它默认不处理 final 字段、静态字段、数组/集合的深层拷贝,也不自动处理嵌套对象——这些属于深拷贝范畴,需额外扩展。
1. 基础反射拷贝:支持 public/private 非 static/final 字段
使用 Class.getDeclaredFields() 获取所有声明字段,调用 setAccessible(true) 突破访问限制,再通过 get() 和 set() 完成赋值:
- 先检查字段是否为 static 或 final,跳过(避免 IllegalAccessException 或无效赋值)
- 对每个兼容字段,用
field.get(src)读值,field.set(dest, value)写入 - 建议捕获
IllegalAccessException和IllegalArgumentException并包装为运行时异常,便于调试
2. 类型安全与基本类型兼容处理
字段类型可能是基本类型(如 int)、包装类(Integer)、String 或自定义引用类型。反射的 get() 方法对基本类型会自动装箱,所以无需特殊转换;但要注意:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 目标对象必须已实例化(不能为 null),且类型与源对象兼容(通常是相同类或子类)
- 若字段是基本类型而源值为 null,
field.set()会抛出异常——可在赋值前判断:若字段是基本类型且值为 null,跳过或设默认值(如 0、false) - 可借助
field.getType().isPrimitive()判断是否为基本类型
3. 忽略特定字段或按需复制
实际使用中常需跳过某些字段(如 id、createTime)。可通过以下方式灵活控制:
- 传入 String 数组(如
ignoreFields = {"id", "version"}),在循环中用Arrays.asList(ignoreFields).contains(field.getName())过滤 - 或使用注解(如
@IgnoreCopy),在反射遍历时检查field.isAnnotationPresent(IgnoreCopy.class) - 也可只复制带特定注解(如
@Copyable)的字段,实现白名单模式
4. 简单示例代码片段
以下是一个最小可用的工具方法(不依赖第三方库):
<font color="#888">
public static void copyProperties(Object src, Object dest) {
if (src == null || dest == null || src.getClass() != dest.getClass()) {
throw new IllegalArgumentException("源和目标对象不能为空且类型需一致");
}
Field[] fields = src.getClass().getDeclaredFields();
for (Field field : fields) {
if (field.getModifiers() == Modifier.STATIC ||
field.getModifiers() == Modifier.FINAL) continue;
field.setAccessible(true);
try {
Object val = field.get(src);
// 基本类型字段不允许设 null,跳过
if (val == null && field.getType().isPrimitive()) continue;
field.set(dest, val);
} catch (IllegalAccessException e) {
throw new RuntimeException("反射复制字段失败: " + field.getName(), e);
}
}
}
</font>
调用方式:copyProperties(user1, user2); 即可将 user1 的非静态非 final 字段值复制到已创建的 user2 实例中。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










