如何在Java中实现对象的深拷贝机制

来源:编程学习作者:新井头衔:网络博主
导读:本期聚焦于小伙伴创作的《如何在Java中实现对象的深拷贝机制》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《如何在Java中实现对象的深拷贝机制》有用,将其分享出去将是对创作者最好的鼓励。

在Java编程中,对象拷贝分为浅拷贝和深拷贝两种类型。浅拷贝只会复制对象本身的基本数据类型字段,对于引用类型字段仅复制引用地址,修改拷贝对象的引用类型字段内容时,原对象对应的字段也会发生变化。深拷贝则会递归复制对象所有层级的字段,包括引用类型指向的对象,拷贝对象与原对象完全独立,互不影响。下面介绍几种常见的深拷贝实现方式。

如何在Java中实现对象的深拷贝机制

一、重写clone方法实现深拷贝

Java中所有类都继承自Object类,Object类提供了clone()方法,默认实现的是浅拷贝。如果要实现深拷贝,需要在类中重写clone()方法,对引用类型字段也调用其clone()方法完成复制。

首先定义引用类型的内部类,该类也需要实现Cloneable接口并重写clone()方法:

// 内部引用类型类
class Address implements Cloneable {
    private String city;
    private String street;

    public Address(String city, String street) {
        this.city = city;
        this.street = street;
    }

    // 重写clone方法,实现Address类的拷贝
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    // getter和setter方法
    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getStreet() {
        return street;
    }

    public void setStreet(String street) {
        this.street = street;
    }
}

然后定义外层类,同样实现Cloneable接口,重写clone()方法时,先调用父类的clone()方法得到浅拷贝对象,再对引用类型的Address字段调用clone()方法完成深拷贝:

// 外层实体类
class User implements Cloneable {
    private String name;
    private int age;
    private Address address;

    public User(String name, int age, Address address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        // 先完成浅拷贝
        User user = (User) super.clone();
        // 对引用类型字段进行深拷贝
        user.address = (Address) this.address.clone();
        return user;
    }

    // getter和setter方法
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }
}

测试重写clone()方法的深拷贝效果:

public class DeepCopyTest {
    public static void main(String[] args) throws CloneNotSupportedException {
        Address address = new Address("北京", "朝阳路");
        User user1 = new User("张三", 20, address);
        // 调用clone方法得到深拷贝对象
        User user2 = (User) user1.clone();

        // 修改拷贝对象的引用类型字段内容
        user2.getAddress().setCity("上海");

        System.out.println("原对象城市:" + user1.getAddress().getCity());
        System.out.println("拷贝对象城市:" + user2.getAddress().getCity());
    }
}

上述代码运行后,原对象的城市仍然是北京,拷贝对象的城市改为上海,说明两者完全独立,深拷贝生效。

二、序列化反序列化实现深拷贝

通过将对象序列化为字节流,再将字节流反序列化为新的对象,也可以实现深拷贝。这种方式要求对象以及对象所有引用的层级对象都实现Serializable接口。

首先修改之前的AddressUser类,实现Serializable接口:

import java.io.Serializable;

class Address implements Serializable {
    private static final long serialVersionUID = 1L;
    private String city;
    private String street;

    public Address(String city, String street) {
        this.city = city;
        this.street = street;
    }

    // getter和setter方法
    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getStreet() {
        return street;
    }

    public void setStreet(String street) {
        this.street = street;
    }
}

class User implements Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
    private int age;
    private Address address;

    public User(String name, int age, Address address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

    // getter和setter方法
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }
}

然后编写序列化反序列化的工具方法实现深拷贝:

import java.io.*;

public class SerializeDeepCopyUtil {
    // 深拷贝方法,传入需要拷贝的对象
    public static <T extends Serializable> T deepCopy(T obj) throws IOException, ClassNotFoundException {
        // 序列化对象到字节流
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(obj);
        oos.flush();

        // 反序列化字节流到新对象
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        return (T) ois.readObject();
    }
}

测试序列化方式的深拷贝效果:

public class DeepCopyTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Address address = new Address("广州", "天河路");
        User user1 = new User("李四", 25, address);
        // 调用序列化工具方法实现深拷贝
        User user2 = SerializeDeepCopyUtil.deepCopy(user1);

        // 修改拷贝对象的引用类型字段
        user2.getAddress().setCity("深圳");

        System.out.println("原对象城市:" + user1.getAddress().getCity());
        System.out.println("拷贝对象城市:" + user2.getAddress().getCity());
    }
}

运行后原对象城市仍为广州,拷贝对象城市改为深圳,说明深拷贝成功。这种方式的优点是不需要手动重写每个引用类型的clone()方法,适合对象层级复杂的场景,缺点是性能相对较差,且所有相关类都需要实现Serializable接口。

三、使用第三方工具类实现深拷贝

实际开发中也可以使用成熟的第三方工具类快速实现深拷贝,比如Apache Commons Lang3提供的SerializationUtils.clone()方法,其底层也是基于序列化反序列化实现,使用起来更加简洁。

首先需要在项目中引入Apache Commons Lang3的依赖,如果是Maven项目,添加如下依赖配置:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.12.0</version>
</dependency>

同样要求拷贝的对象以及所有引用层级的对象实现Serializable接口,之后直接使用工具类即可完成深拷贝:

import org.apache.commons.lang3.SerializationUtils;

public class DeepCopyTest {
    public static void main(String[] args) {
        Address address = new Address("杭州", "西湖路");
        User user1 = new User("王五", 30, address);
        // 使用SerializationUtils实现深拷贝
        User user2 = SerializationUtils.clone(user1);

        // 修改拷贝对象的引用类型字段
        user2.getAddress().setCity("成都");

        System.out.println("原对象城市:" + user1.getAddress().getCity());
        System.out.println("拷贝对象城市:" + user2.getAddress().getCity());
    }
}

除了Apache Commons Lang3,还可以使用Spring框架提供的BeanUtils结合自定义逻辑实现深拷贝,或者使用Gson、Jackson等JSON工具将对象转为JSON字符串再转回对象实现深拷贝,不过JSON方式会忽略transient修饰的字段,使用时需要注意。

四、不同深拷贝实现方式的对比

下面通过表格对比几种常见深拷贝实现方式的特点:

实现方式优点缺点适用场景
重写clone方法性能较好,不需要额外依赖需要手动处理每个引用类型的拷贝逻辑,对象层级复杂时工作量大对象结构固定、层级较少的场景
序列化反序列化不需要手动处理每个引用类型的拷贝,通用性强性能较差,所有相关类需要实现Serializable接口对象层级复杂、不希望手动编写拷贝逻辑的场景
第三方工具类使用简单,代码简洁需要引入额外依赖,底层如果是序列化方式则性能较差项目已经引入对应依赖、追求开发效率的场景

开发者可以根据项目的实际需求和场景,选择合适的深拷贝实现方式,在保证功能正确的同时兼顾开发效率和运行性能。

Java深拷贝对象拷贝clone_方法序列化修改时间:2026-07-20 05:51:37

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。