当前位置:首页 > 技术 > 正文内容

Java中对象的浅拷贝与深拷贝实现及差异

访客 技术 2026年10月7日 1

Java中直接通过赋值操作(如 Person b = a;)仅复制对象引用地址,导致两个变量指向堆中同一实例。修改任一变量的属性将影响对方。为避免此问题,需使用拷贝机制——核心是实现 Object 类的 clone() 方法,或借助序列化技术生成独立副本。

浅拷贝(Shallow Copy)

浅拷贝仅创建新对象自身,但若字段为引用类型,则拷贝其引用地址,即:新旧对象共享嵌套对象。

实现浅拷贝需满足:

  • 类实现 Cloneable 接口(标记接口,避免抛出 CloneNotSupportedException);
  • 重写 clone() 方法并设为 public。

示例:包含基本类型字段和引用类型字段的类 People。

public class Car implements Cloneable {
    private String name;
    private String color;

    // getter & setter 省略

    @Override
    public Car clone() throws CloneNotSupportedException {
        return (Car) super.clone();
    }
}

public class People implements Cloneable {
    private String name;
    private int age;
    private Car car;

    // getter & setter 省略

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone(); // 仅 copy 当前对象基本类型字段,引用字段仍共享
    }

    @Override
    public String toString() {
        return "People{name='" + name + "', age=" + age + ", car=" + car + "}";
    }
}

测试代码及输出:

public static void main(String[] args) throws Exception {
    People p1 = new People();
    p1.setName("zhangsan");
    p1.setAge(23);
    Car c = new Car();
    c.setName("Ferrari");
    c.setColor("red");
    p1.setCar(c);

    People p2 = (People) p1.clone();
    System.out.println("p1: " + p1);
    System.out.println("p2: " + p2);
    // 输出:
    // p1: People{name='zhangsan', age=23, car=Car@abc123}
    // p2: People{name='zhangsan', age=23, car=Car@abc123}
    // 地址相同 → 共享嵌套对象
}

验证:修改 p2.car 的颜色,p1.car 也跟着变化,证明两者共享同一 Car 实例。


深拷贝(Deep Copy)

深拷贝需递归复制所有层级的引用对象,确保新对象与原对象完全独立。可采用以下两种方式:

方式一:手动实现(重写嵌套对象的 clone)

对 People 的 clone 方法进行扩展,显式 clone 其引用字段:

public class Car implements Cloneable {
    // ...同上
}

public class People implements Cloneable {
    // ...字段同上

    @Override
    public Object clone() throws CloneNotSupportedException {
        People cloned = (People) super.clone();
        cloned.setCar(car.clone()); // 关键:逐级克隆引用对象
        return cloned;
    }
}

测试结果:p1.car 与 p2.car 地址不同,互不影响。

方式二:基于序列化实现深拷贝

该方式不依赖手动递归,适用于多层嵌套或复杂对象结构,前提是所有相关类均实现 Serializable 接口。

import java.io.*;

public class DeepCloneUtil {
    public static <T extends Serializable> T deepClone(T obj) throws Exception {
        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();
    }
}

调用示例:

People original = ...; // 已初始化
People copy = DeepCloneUtil.deepClone(original);
// copy 中嵌套对象均非原对象引用,地址唯一

序列化法优势:

  • 无需为每个类实现 Cloneable 和重写 clone();
  • 支持任意深度的对象图拷贝;
  • 更健壮,不易因遗漏引用字段导致浅拷贝。

注意:Spring 或其他框架中的代理对象、transient 字段、非序列化依赖项需特殊处理。

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

linux screen 用法详情 (nohup 的替代方案)

一、screen 是什么?能干嘛?screen 是一个终端复用器,可以:在一个 SSH 会话中开多个“虚拟终端”SSH 断线后,程序仍然在后台运行随时重新连接到原来的会话特别适合:nohup 的替代方案跑脚本 / 爬虫 / 训练模型运维、远程开发二、安装 screen# CentOS / Rocky / Almayum install -y screen# Debian / Ubuntuapt i...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。