🛠️ 步骤一:定义测试类

import java.util.Objects;

class Address {
    private String city;
    private String street;

    // 构造器、Getter & Setter、toString()
}
import java.util.Date;

class User implements Cloneable {
    private String name;
    private int age;
    private Date birthDate;
    private Address address;

    // 构造器、Getter & Setter、toString()

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

🧪 步骤二:使用 clone() 实现浅拷贝

User user1 = new User("Alice", 30, new Date(), new Address("Beijing", "Chaoyang"));
User user2 = (User) user1.clone();

// 修改副本中的 address
user2.getAddress().setCity("Shanghai");

// 输出 user1.address.city 也会变成 Shanghai
System.out.println(user1.getAddress().getCity()); // Shanghai ❗

💡 结论:clone() 默认是浅拷贝,只复制对象本身,不复制引用字段。


🧩 步骤三:手动实现深拷贝(推荐)

@Override
protected Object clone() throws CloneNotSupportedException {
    User newUser = (User) super.clone();
    newUser.setAddress((Address) this.address.clone()); // 手动拷贝嵌套对象
    newUser.setBirthDate((Date) this.birthDate.clone());
    return newUser;
}

📌 注意:需要为每个嵌套类也实现 Cloneableclone(),否则仍是浅拷贝。


🧨 步骤四:使用序列化实现通用深拷贝

public static <T extends Serializable> T deepCopy(T object) {
    try {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(object);
        oos.flush();
        oos.close();

        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        return (T) ois.readObject();
    } catch (Exception e) {
        throw new RuntimeException("Deep copy failed", e);
    }
}

✅ 优点:适用于任意复杂对象
❌ 缺点:必须实现 Serializable,性能较低


▶️ 步骤五:使用 JSON 序列化(推荐)

使用 Jackson:

ObjectMapper mapper = new ObjectMapper();
User copy = mapper.readValue(mapper.writeValueAsBytes(original), User.class);

使用 Gson:

Gson gson = new Gson();
User copy = gson.fromJson(gson.toJson(original), User.class);

✅ 优点:无需实现接口,支持非 Serializable 类
❌ 缺点:依赖 JSON 转换库,性能略差


📦 步骤六:使用 Apache Commons Lang(一行搞定)

User copy = SerializationUtils.clone(original);

前提:类必须实现 Serializable 接口。