Java中 继承体系下深拷贝怎么递归复制父类私有属性

梦萱君_5477

梦萱君_5477

2026-07-20

195人浏览

原创

java深拷贝继承体系中,父类私有属性不可直接访问,应通过父类提供clone()等受保护方法委托复制;子类调用super.clone()获取已深拷贝的父类状态,再处理自身字段。

java中 继承体系下深拷贝怎么递归复制父类私有属性

Java 中继承体系下的深拷贝,无法直接访问或复制父类的私有属性(private),这是由 Java 的封装机制和访问控制规则决定的。但“递归复制父类私有属性”这个需求,本质上不是要绕过访问限制,而是要在保证语义正确、对象独立的前提下,让子类副本完整继承父类状态。关键在于:不靠“读取私有字段”,而靠“委托父类能力”来完成深拷贝。

下面分几个核心角度说明怎么做:

父类必须提供可被子类调用的深拷贝能力

私有属性虽不可见,但父类可通过受保护(protected)或公有(public)方法暴露其复制逻辑。最合理的方式是:

  • 父类实现 Cloneable 并重写 clone(),且该方法内部已对自身所有字段(包括私有字段)完成深拷贝;
  • 子类在重写 clone() 时,调用 super.clone() 获取父类部分的完整副本,再处理自己的引用字段。
class Parent implements Cloneable {
    private String name;
    private Address address; // 可变引用类型

    public Parent(String name, Address address) {
        this.name = name;
        this.address = address;
    }

    @Override
    protected Parent clone() throws CloneNotSupportedException {
        Parent cloned = (Parent) super.clone(); // 浅拷贝本层字段(name 是 String,安全;address 是引用,需深拷)
        cloned.address = this.address != null ? this.address.clone() : null;
        return cloned;
    }
}

class Child extends Parent implements Cloneable {
    private List<string> tags;

    public Child(String name, Address address, List<string> tags) {
        super(name, address);
        this.tags = tags;
    }

    @Override
    protected Child clone() throws CloneNotSupportedException {
        Child cloned = (Child) super.clone(); // 调用父类 clone → 已含 name + 深拷贝后的 address
        cloned.tags = new ArrayList(this.tags); // 基本类型集合,直接构造新实例(浅拷贝安全)
        return cloned;
    }
}</string></string>

✅ 这里 super.clone() 不是简单复制内存地址——它触发的是父类重写的 clone() 方法,而该方法已负责私有字段 address 的深拷贝。子类无需、也不应尝试反射读取 name 或 address 字段。

不推荐但技术上可行的方式:反射(仅限调试/特殊场景)

如果父类未提供任何克隆支持,又无法修改源码,可用反射强行访问私有字段,但需注意:

Java Maven Common
Java Maven Common

Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。

下载
  • 必须调用 setAccessible(true),违反封装原则,生产环境慎用;
  • 仍需自行处理每个私有字段的深拷贝逻辑(如判断是否为 null、是否可克隆、是否循环引用等);
  • 无法自动处理父类中更上层的继承链(比如 Parent 继承自 GrandParent),需逐级向上反射。
Field field = Parent.class.getDeclaredField("address");
field.setAccessible(true);
Address addr = (Address) field.get(originalParent);
clonedParentAddress = addr != null ? addr.clone() : null;

⚠️ 这种方式脆弱、易出错、破坏模块边界,不应作为标准方案。

使用序列化替代 clone(规避访问限制)

ObjectOutputStream / ObjectInputStream 不依赖字段可见性,只要整个继承链上的所有类都实现 Serializable,就能自动完成深拷贝,天然包含所有私有字段:

public static <t extends serializable> T deepCopy(T obj) throws IOException, ClassNotFoundException {
    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();
}</t>

✅ 优点:无需修改父类,不关心 private 或继承结构,全自动。
❌ 缺点:性能低、要求所有类可序列化、不支持 transient 字段、无法处理某些 JVM 特殊对象(如 Thread、Socket)。

构造器注入 + 不可变设计(根本性解法)

如果能重构,建议让父类使用不可变模式或带副本构造的构造器:

  • 私有字段全部 final;
  • 提供 Parent(Parent other) 构造器,内部对引用字段做深拷贝;
  • 子类 clone() 中通过 new Child(other) 构建,自然继承父类状态。
class Parent {
    private final String name;
    private final Address address;

    public Parent(Parent other) {
        this.name = other.name;
        this.address = other.address != null ? new Address(other.address) : null;
    }
}

这种方式把深拷贝逻辑收拢到构造阶段,清晰、安全、可测试,且完全避开 private 访问难题。

不复杂但容易忽略:深拷贝的关键从来不是“怎么读私有字段”,而是“谁负责复制、何时复制、是否递归到底”。父类应对其状态完整性负责,子类只需组合与扩展。

Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

java

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

2023.06.15

10897

6

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

2023.07.05

8022

9

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

2023.07.31

6952

8

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.01

1164

3

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.02

948

3

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

1416

5

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

2869

5

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

2023.08.03

20151

3

配置java环境变量
配置java环境变量

配置Java环境变量是为了让操作系统能够识别和使用Java的相关命令和功能。本专题为大家提供配置java环境变量相关文章,帮助大家解决问题。

2023.08.03

1255

8

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习