Java案例怎么克隆对象数据?

wen java案例 11

本文目录导读:

Java案例怎么克隆对象数据?

  1. 实现 Cloneable 接口(浅克隆)
  2. 手动深克隆(重写clone方法)
  3. 使用拷贝构造器
  4. 使用序列化(最彻底的深克隆)
  5. 使用第三方库(推荐)
  6. 使用Java Records(Java 16+)
  7. 实际案例:完整深克隆示例
  8. 推荐方案

在Java中克隆对象数据有多种方式,我将为你详细介绍几种主流方法:

实现 Cloneable 接口(浅克隆)

public class Student implements Cloneable {
    private String name;
    private int age;
    private Address address; // 引用类型
    // 构造器、getter/setter省略
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone(); // 默认浅克隆
    }
}
// 使用
Student s1 = new Student("张三", 20, new Address("北京"));
Student s2 = (Student) s1.clone(); // 浅克隆

缺点:引用类型字段只复制引用,不复制对象本身。

手动深克隆(重写clone方法)

@Override
protected Object clone() throws CloneNotSupportedException {
    // 先浅克隆
    Student cloned = (Student) super.clone();
    // 手动深克隆引用类型
    if (this.address != null) {
        cloned.address = (Address) this.address.clone();
    }
    return cloned;
}

需要确保所有引用类型也实现了Cloneable接口。

使用拷贝构造器

public class Student {
    private String name;
    private int age;
    private Address address;
    // 拷贝构造器
    public Student(Student other) {
        this.name = other.name;
        this.age = other.age;
        // 深克隆引用类型
        this.address = new Address(other.address); // Address也需要拷贝构造器
    }
}
// 使用
Student s2 = new Student(s1);

使用序列化(最彻底的深克隆)

import java.io.*;
public class CloneUtil {
    @SuppressWarnings("unchecked")
    public static <T extends Serializable> T deepClone(T obj) {
        try {
            // 序列化
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(obj);
            // 反序列化
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);
            return (T) ois.readObject();
        } catch (Exception e) {
            throw new RuntimeException("克隆失败", e);
        }
    }
}
// 使用
Student s2 = CloneUtil.deepClone(s1);

要求:所有类必须实现Serializable接口。

使用第三方库(推荐)

Apache Commons Lang3

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.12.0</version>
</dependency>
// 需要实现Serializable
Student s2 = SerializationUtils.clone(s1);

使用JSON序列化(Jackson/Gson)

// Jackson方式
ObjectMapper mapper = new ObjectMapper();
Student s2 = mapper.readValue(mapper.writeValueAsString(s1), Student.class);
// Gson方式
Gson gson = new Gson();
Student s2 = gson.fromJson(gson.toJson(s1), Student.class);

使用Java Records(Java 16+)

Record类型自动提供了复制方法:

public record Student(String name, int age, Address address) {
    // 自动生成:构造器、equals、hashCode、toString
}
// 使用with修改某些字段
Student s2 = new Student("张三", 20, new Address("北京"));
Student s3 = new Student(s2.name(), s2.age(), new Address("上海"));

实际案例:完整深克隆示例

import java.io.*;
class Address implements Serializable {
    private static final long serialVersionUID = 1L;
    private String city;
    public Address(String city) {
        this.city = city;
    }
    // getter/setter...
}
class Employee implements Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
    private Address address;
    private Salary salary; // 另一个引用类型
    // 使用序列化实现深克隆
    public Employee deepClone() {
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(this);
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);
            return (Employee) ois.readObject();
        } catch (Exception e) {
            throw new RuntimeException("克隆失败", e);
        }
    }
}
// 测试
public class TestClone {
    public static void main(String[] args) {
        Employee e1 = new Employee("张三", new Address("北京"), new Salary(10000));
        Employee e2 = e1.deepClone();
        // 修改e2的地址,不会影响e1
        e2.getAddress().setCity("上海");
        System.out.println(e1.getAddress().getCity()); // 输出:北京(深克隆成功)
    }
}

推荐方案

  1. 简单对象:使用拷贝构造器
  2. 复杂对象图:使用序列化方式
  3. 性能要求高:手动实现深克隆
  4. 企业级应用:使用Apache Commons或JSON序列化

选择哪种方式取决于你的具体需求,包括性能要求、对象复杂度、是否需要完全独立等。

抱歉,评论功能暂时关闭!