深拷贝需智能区分对象类型:基本类型及包装类、不可变类型直接复制;普通自定义对象递归处理,跳过static/transient/final字段;集合需按容器类型重建并逐元素深拷贝;通过ThreadLocal缓存防循环引用。

深拷贝时区分普通对象和包装对象,核心在于类型判断逻辑要足够智能——不能只看是不是基本类型,还要识别包装类、不可变类型、集合容器等不同语义的“安全可跳过”或“必须递归”的情形。
识别包装类与基本类型的自动映射
Java中int/Integer、boolean/Boolean等成对存在,深拷贝工具需内置类型兼容表。遇到Integer字段时,直接赋值即可,无需new或clone;但遇到Long[]数组,则要逐个元素处理。常见做法是维护一个简单类型集合:
- 基本类型(int、char、boolean等)及其对应包装类(Integer、Character、Boolean等)视为“值安全”,直接复制
- String、LocalDateTime、BigDecimal、BigInteger 等不可变类型也归入该类,复制引用无副作用
- 判断逻辑通常用 Class.isPrimitive() + Class.isAssignableFrom() 或白名单匹配
普通自定义对象需递归深拷贝
非简单类型且非不可变类的对象,默认按需递归处理。关键点是排除干扰项:
- 跳过static、transient、final修饰的字段(除非明确要求保留)
- 检测是否实现Serializable或Cloneable,作为深拷贝可行性的快速参考
- 对目标类无参构造函数做预检,避免反序列化或反射实例化失败
- 遇到父类字段时,沿继承链向上扫描并拷贝,但不拷贝Object类的默认字段
集合与泛型的兼容性处理
List
- 先识别外层容器类型(ArrayList → 新建ArrayList,HashSet → 新建HashSet)
- 再尝试从泛型声明或首元素类型推测元素类型,用于后续递归拷贝
- 若元素为简单类型或不可变对象,直接add;若为自定义对象,调用深拷贝方法逐个处理
- 对Map,key和value分别判断:String作key可直接复用;User作value则必须深拷贝
规避循环引用与空值风险
真实业务对象常含双向关联(如Order ↔ User ↔ Order),不加控制会导致栈溢出。稳妥做法包括:
- 用ThreadLocal
- null值统一跳过,不抛异常也不创建占位对象,保持语义一致
- 对Date、Calendar等可变但有clone()方法的类,优先调用其自有clone逻辑,而非走通用反射路径

















