Java中的深克隆与浅克隆

Java克隆机制详解
本文详细介绍了Java中对象克隆的实现方式,包括浅克隆和深克隆的区别及应用场景。通过具体示例展示了如何实现两种克隆方式,并解释了String类型在克隆过程中的特殊行为。
前言

  克隆,即复制一个对象,该对象的属性与被复制的对象一致,如果不使用Object类中的clone方法实现克隆,可以自己new出一个对象,并对相应的属性进行赋值,这样也能实现克隆的目的。但当对象属性较多时,这样的克隆方式会比较麻烦,所以Object类中实现了clone方法,用于克隆对象。


Java中的克隆分为浅克隆与深克隆
一、实现克隆的方式

  1.对象的类需要实现Cloneable接口
  2.重写Object类中的clone()方法
  3.根据重写的clone()方法得到想要的克隆结果,例如浅克隆与深克隆。

二、浅克隆与深克隆的区别

  浅克隆:复制对象时仅仅复制对象本身,包括基本属性,但该对象的属性引用其他对象时,该引用对象不会被复制,即拷贝出来的对象与被拷贝出来的对象中的属性引用的对象是同一个。

  深克隆:复制对象本身的同时,也复制对象包含的引用指向的对象,即修改被克隆对象的任何属性都不会影响到克隆出来的对象。

image

代码如下:

class Person implements Cloneable{

    private int age;
    private String name;
    
    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }
    
    public void setAge(int age) {
        this.age = age;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    @Override
    public String toString() {
        return "Person{" +
        "age=" + age +
        ", name='" + name + '\'' +
        '}';
    }
    
    @Override
        protected Person clone() throws CloneNotSupportedException { 
        return (Person)super.clone(); //调用父类的clone方法
    }
}

测试代码:

public class CloneTest {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person person = new Person(22,"LiLei");
        Person newPerson = person.clone();
        person.setAge(21);
        person.setName("HanMeimei");
        System.out.println(person.toString());
        System.out.println(newPerson.toString());
    }
}

测试结果:

Person{age=21, name='HanMeimei'}
Person{age=22, name='LiLei'}

  即在克隆出新的对象后,修改被克隆对象的基本属性,并不会影响克隆出来的对象。但当被克隆的对象的属性引用其他对象时,此时会有不同的结果。

代码如下:

/**
* 学生类
*/
class Student implements Cloneable{
    private String name;
    private Achievement achievement; //成绩
    
    public Student(String name, Achievement achievement) {
        this.name = name;
        this.achievement = achievement;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public void setAchievement(Achievement achievement) {
        this.achievement = achievement;
    }
    
    public Achievement getAchievement() {
        return achievement;
    }
    
    @Override
    public String toString() {
        return "Student{" +
        "name='" + name + '\'' +
        ", achievement=" + achievement +
        '}';
    }
    
    @Override
    protected Student clone() throws CloneNotSupportedException {
        return (Student) super.clone(); 
    }
}

/**
* 成绩类
*/
class Achievement implements Cloneable{
    private float Chinese;
    private float math;
    private float English;
    
    public Achievement(float chinese, float math, float english) {
        Chinese = chinese;
        this.math = math;
        English = english;
    }
    
    public void setChinese(float chinese) {
        Chinese = chinese;
    }
    
    public void setMath(float math) {
        this.math = math;
    }
    
    public void setEnglish(float english) {
        English = english;
    }
    
    @Override
    public String toString() {
        return "Achievement{" +
        "Chinese=" + Chinese +
        ", math=" + math +
        ", English=" + English +
        '}';
    }
    
    @Override
    protected Achievement clone() throws CloneNotSupportedException {
        return (Achievement) super.clone();
    }
}

测试代码:

public class CloneTest {
    public static void main(String[] args) throws CloneNotSupportedException {
        Achievement achievement = new Achievement(100,100,100);
        Student student = new Student("LiLei",achievement);
        // 克隆出一个对象
        Student newStudent = student.clone();
        
        // 修改原有对象的属性
        student.setName("HanMeimei");
        student.getAchievement().setChinese(90);
        student.getAchievement().setEnglish(90);
        student.getAchievement().setMath(90);
        
        System.out.println(newStudent);
        System.out.println(student);
    
    }
}

测试结果:

Student{name='LiLei', achievement=Achievement{Chinese=90.0, math=90.0, English=90.0}}
Student{name='HanMeimei', achievement=Achievement{Chinese=90.0, math=90.0, English=90.0}}

  以上现象表明,上述克隆方式为浅克隆,并不会克隆对象的属性引用的对象,当修改被克隆对象的成绩时,克隆出来的对象也会跟着改变,即两个对象的属性引用指向的是同一个对象。
  但只要修改一下Student类中重写的clone()方法,即可实现深克隆。

修改代码如下:

@Override
protected Student clone() throws CloneNotSupportedException {
    Student student = (Student) super.clone();
    Achievement achievement = student.getAchievement().clone();
    student.setAchievement(achievement);
    return student;
}

测试结果:

Student{name='LiLei', achievement=Achievement{Chinese=100.0, math=100.0, English=100.0}}
Student{name='HanMeimei', achievement=Achievement{Chinese=90.0, math=90.0, English=90.0}}

  即在Student类中的clone()方法中再克隆一次Achievement对象,并赋值给Student对象。

  值得一提的是,上文所说的浅拷贝只会克隆基本数据属性,而不会克隆引用其他对象的属性,但String对象又不属于基本属性,这又是为什么呢?

  这是因为String对象是不可修改的对象,每次修改其实都是新建一个新的对象,而不是在原有的对象上修改,所以当修改String属性时其实是新开辟一个空间存储String对象,并把引用指向该内存,而克隆出来的对象的String属性还是指向原有的内存地址,所以String对象在浅克隆中也表现得与基本属性一样。

AI 代码审查Review工具 是一个旨在自动化代码审查流程的工具。它通过集成版本控制系统(如 GitHub GitLab)的 Webhook,利用大型语言模型(LLM)对代码变更进行分析,并将审查意见反馈到相应的 Pull Request 或 Merge Request 中。此外,它还支持将审查结果通知到企业微信等通讯工具。 一个基于 LLM 的自动化代码审查助手。通过 GitHub/GitLab Webhook 监听 PR/MR 变更,调用 AI 分析代码,并将审查意见自动评论到 PR/MR,同时支持多种通知渠道。 主要功能 多平台支持: 集成 GitHub GitLab Webhook,监听 Pull Request / Merge Request 事件。 智能审查模式: 详细审查 (/github_webhook, /gitlab_webhook): AI 对每个变更文件进行分析,旨在找出具体问题。审查意见会以结构化的形式(例如,定位到特定代码行、问题分、严重程度、分析建议)逐条评论到 PR/MR。AI 模型会输出 JSON 格式的分析结果,系统再将其转换为多条独立的评论。 通用审查 (/github_webhook_general, /gitlab_webhook_general): AI 对每个变更文件进行整体性分析,并为每个文件生成一个 Markdown 格式的总结性评论。 自动化流程: 自动将 AI 审查意见(详细模式下为多条,通用模式下为每个文件一条)发布到 PR/MR。 在所有文件审查完毕后,自动在 PR/MR 中发布一条总结性评论。 即便 AI 未发现任何值得报告的问题,也会发布相应的友好提示总结评论。 异步处理审查任务,快速响应 Webhook。 通过 Redis 防止对同一 Commit 的重复审查。 灵活配置: 通过环境变量设置基
【直流微电网】径向直流微电网的状态空间建模线性化:一种耦合DC-DC变换器状态空间平均模型的方法 (Matlab代码实现)内容概要:本文介绍了径向直流微电网的状态空间建模线性化方法,重点提出了一种基于耦合DC-DC变换器的状态空间平均模型的建模策略。该方法通过数学建模手段对直流微电网系统进行精确的状态空间描述,并对其进行线性化处理,以便于系统稳定性分析控制器设计。文中结合Matlab代码实现,展示了建模仿真过程,有助于研究人员理解复现相关技术,推动直流微电网系统的动态性能研究工程应用。; 适合人群:具备电力电子、电力系统或自动化等相关背景,熟悉Matlab/Simulink仿真工具,从事新能源、微电网或智能电网研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①掌握直流微电网的动态建模方法;②学习DC-DC变换器在耦合条件下的状态空间平均建模技巧;③实现系统的线性化分析并支持后续控制器设计(如电压稳定控制、功率分配等);④为科研论文撰写、项目仿真验证提供技术支持代码参考。; 阅读建议:建议读者结合Matlab代码逐步实践建模流程,重点关注状态变量选取、平均化处理线性化推导过程,同时可扩展应用于更复杂的直流微电网拓扑结构中,提升系统分析设计能力。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值