Java 对象深克隆(Deep Clone)的几种实现方式

深克隆是指创建一个新对象,并递归复制原对象及其引用的所有对象,使得新对象与原对象完全独立,修改其中一个不会影响另一个。以下是Java中实现深克隆的几种主要方式:

1. 序列化/反序列化方式

这是最通用的深克隆方法,适用于任何实现了Serializable接口的对象。

import java.io.*;

public class DeepCloneUtil {
    
    @SuppressWarnings("unchecked")
    public static <T extends Serializable> T clone(T obj) {
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
             ObjectOutputStream oos = new ObjectOutputStream(baos)) {
            
            oos.writeObject(obj);
            
            try (ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
                 ObjectInputStream ois = new ObjectInputStream(bais)) {
                
                return (T) ois.readObject();
            }
        } catch (IOException | ClassNotFoundException e) {
            throw new RuntimeException("Deep clone failed", e);
        }
    }
}

// 使用示例
Person original = new Person("张三", 25);
Person cloned = DeepCloneUtil.clone(original);

优点

  • 通用性强,适用于任何可序列化对象
  • 实现简单

缺点

  • 性能较低(涉及I/O操作)
  • 要求所有引用的对象都必须实现Serializable接口
  • 无法克隆transient字段

2. 手动实现Cloneable接口

通过重写clone()方法实现深克隆。

class Address implements Cloneable {
    private String city;
    private String street;
    
    // 构造方法、getter/setter省略
    
    @Override
    protected Address clone() {
        try {
            return (Address) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new AssertionError(); // 不会发生
        }
    }
}

class Person implements Cloneable {
    private String name;
    private int age;
    private Address address;
    
    // 构造方法、getter/setter省略
    
    @Override
    protected Person clone() {
        try {
            Person cloned = (Person) super.clone();
            cloned.address = this.address.clone(); // 深克隆引用对象
            return cloned;
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }
    }
}

// 使用示例
Person original = new Person("张三", 25, new Address("北京", "长安街"));
Person cloned = original.clone();

优点

  • 性能较好
  • 可以精确控制克隆过程

缺点

  • 需要为每个类手动实现克隆逻辑
  • 当对象图复杂时,实现繁琐
  • 需要所有引用对象都实现Cloneable

3. 使用第三方库

(1) Apache Commons Lang - SerializationUtils

import org.apache.commons.lang3.SerializationUtils;

Person original = new Person("张三", 25);
Person cloned = SerializationUtils.clone(original);

(2) JSON序列化方式(如Gson/Jackson)

import com.google.gson.Gson;

Gson gson = new Gson();
Person original = new Person("张三", 25);
Person cloned = gson.fromJson(gson.toJson(original), Person.class);

优点

  • 实现简单
  • 不要求对象实现SerializableCloneable

缺点

  • JSON序列化会丢失对象类型信息(如多态)
  • 性能比原生序列化更低
  • 无法处理循环引用

4. 使用Java深层复制工具库

Cloner库(https://github.com/kostaskougios/cloning):

import com.rits.cloning.Cloner;

Cloner cloner = new Cloner();
Person original = new Person("张三", 25);
Person cloned = cloner.deepClone(original);

优点

  • 功能强大,可以处理复杂对象图
  • 性能较好
  • 不需要实现特定接口

缺点

  • 需要引入第三方依赖

5浅克隆和深克隆区别


特性                         浅克隆                                                   深克隆
————————————————————————————————————————
基本类型字段              复制值                                             复制值
————————————————————————————————————————
引用类型字段          复制引用地址(共享对象)             递归复制对象(无共享)
————————————————————————————————————————
内存开销                         小                                            大(递归复制整个对象图)
————————————————————————————————————————
实现复杂度            简单(自动调用 super.clone())        复杂(需手动处理所有引用类型)
————————————————————————————————————————
对象独立性            引用类型字段不独立                        所有字段完全独立
————————————————————————————————————————
典型应用场景         不可变引用类型(如 String)            需要完全隔离的复杂对象
————————————————————————————————————————

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐