浅克隆和深克隆

为什么要使用克隆

         在业务中,有时候需要对对象进行克隆。例如Student对象,如果如下代码进行“克隆”,其实是引用重新赋值

     Student stu1 = new Student();
     stu1.setName("测试1");
     stu1.setAge(23);
     Student stu2 = stu1;
  

      在上述代码中如果,对stu1,或者stu2的属性进行改变,两者的属性都会发生相同的改变。这样赋值,堆中还是只用一个Student对象,只不过在栈中存在stu1,stu2两个引用指向堆中的Student对象。

浅克隆

     针对对象中的属性没有引用类型,都是基本数据类型。例如如下代码:

  1.首先创建Student对象

            创建Student对象,其中的属性是String类型的name,int类型的age。克隆需要继承Cloneable接口,这个接口是标识性接口。然后重写object中的clone方法。

package com.wx.qianKeLong;

public class Student implements Cloneable{
    private String  name;
    private int age;

    //private Address address;

    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;
//    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        Student student = null;
        student = (Student) super.clone();
       // student.address = (Address) address.clone();
        return student;
    }


    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
               // ", address=" + address +
                '}';
    }
}

  2.创建测试类

    在该类中,创建student对象,然后对student中的属性中name设置为wx,age设置为24。然后对student对象进行克隆,克隆后的对象为student1,然后student1对属性进行改变,name为wx2,age为25.最后将student的引用赋值给student3,student3对属性name和age进行修改

package com.wx.qianKeLong;

public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        Student student = new Student();
        //Address address= new Address();
        //address.setName("China");
        student.setName("wx");
        student.setAge(24);
        System.out.println("未修改之前的Student:"+student);
        //student.setAddress(address);
        Student student1 = (Student) student.clone();
        //address.setName("American");
        student1.setName("wx2");
        student1.setAge(25);
        Student student2 = student;
        student2.setName("wx3");
        student2.setAge(16);
        System.out.println(student);
        System.out.println(student1);
        System.out.println(student2);
        System.out.println("===============================");
    }
}

结果

                                           

通过结果说明,student1通过克隆产生了新的对象,而student2只是引用的复制,当student2对属性进行修改,student的属性也发生修改。

深克隆-出现问题

1.创建Student类

    创建Student类,属性为String类型的name,int类型的age,还有引用类型的 address。

package com.wx.qianKeLong;

public class Student implements Cloneable{
    private String  name;
    private int age;

    private Address address;

    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;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        Student student = null;
        student = (Student) super.clone();
        //student.address = (Address) address.clone();
        return student;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address=" + address +
                '}';
    }
}

2.创建Address类

  创建Address类,属性为String类型的name

package com.wx.qianKeLong;

public class Address implements Cloneable{
    private String name;

    public String getName() {
        return name;
    }

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

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public String toString() {
        return "Address{" +
                "name='" + name + '\'' +
                '}';
    }
}

3.创建测试类

    在测试类中,创建student对象,然后创建Address对象,对student对象中address属性进行赋值。然后对student对象进行克隆。克隆之后对address对象中name属性进行修改。如果是深克隆的话,对address对象进行修改,改变的话应该是student对象中的address属性,可是结果确实两个对象都发生修改,因此此克隆是浅克隆,没有对引用类型进行克隆,引用类型依然是引用的赋值。

package com.wx.qianKeLong;

public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        Student student = new Student();
        Address address= new Address();
        address.setName("China");
        student.setName("wx");
        student.setAge(24);
        student.setAddress(address);
        Student student1 = (Student) student.clone();
        address.setName("American");
        System.out.println(student);
        System.out.println(student1);
        System.out.println("===============================");
    }
}

结果

                                

解决深克隆出现的问题

1.创建student对象

   创建student对象,属性是String类型的name,int类型的age,Address类型的address

package com.wx.qianKeLong;

public class Student implements Cloneable{
    private String  name;
    private int age;

    private Address address;

    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;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        Student student = null;
        student = (Student) super.clone();
        student.address = (Address) address.clone();
        return student;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address=" + address +
                '}';
    }
}

2.创建address对象

  创建Address类,实现Cloneable接口,重写clone()方法。

package com.wx.qianKeLong;

public class Address implements Cloneable{
    private String name;

    public String getName() {
        return name;
    }

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

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public String toString() {
        return "Address{" +
                "name='" + name + '\'' +
                '}';
    }
}

3.创建测试类

在测试类中,首先对student中的属性进行赋值,然后进行克隆。克隆之后的对象是student2.此时对address中的name属性进行修改,发现student中的address属性发生修改,而克隆之后的address属性没有修改。因为address属性是属于student的,在克隆后student1的address也进行克隆。此时address对name属性进行修改只会影响sutdent而不会影响student1.

package com.wx.qianKeLong;

public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        Student student = new Student();
        Address address= new Address();
        address.setName("China");
        student.setName("wx");
        student.setAge(24);
        student.setAddress(address);
        Student student1 = (Student) student.clone();
        address.setName("American");
        System.out.println(student);
        System.out.println(student1);
        System.out.println("===============================");
    }
}

结果

                             

深克隆进阶-采用序列化和反序列话进行克隆

  如果,在克隆中,多个类采用层层继承,那么在使用深克隆的时候就会产生在每一个类中都要重写clone方法,然后进行克隆。太过于繁琐。为了避免此问题,可以采用序列化和反序列化进行克隆。

1.创建Outer类

    创建Outer类,属性为String类型的name,Inner类型的inner。然后创建getInstance方法,进行序列化和反序列化操作。

package com.wx.xuLieHuaKeLong;

import java.io.*;

public class Outer implements Serializable{
    private String name;
    private Inner inner;

    public Inner getInner() {
        return inner;
    }

    public void setInner(Inner inner) {
        this.inner = inner;
    }

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "Outer{" +
                "name='" + name + '\'' +
                ", inner=" + inner +
                '}';
    }

    private static final long serialVersionUID = 123712831982744L;
    public Outer getInstance(){
        Outer outer = null;
        try {
            //将对象转化为流
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
            objectOutputStream.writeObject(this);
            //将流转化为对象
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
            ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
            outer = (Outer) objectInputStream.readObject();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return  outer;
    }
}

2.创建Inner类

创建inner类,实现serializable

package com.wx.xuLieHuaKeLong;

import java.io.Serializable;

public class Inner implements Serializable{
    private String name;

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "Inner{" +
                "name='" + name + '\'' +
                '}';
    }
}

3.创建Test测试类

创建outer对象,然后getinstance进行克隆,克隆之后对inner属性进行修改,只影响outer对象中inner的属性,instance对象中的inner属性不发生变化。

package com.wx.xuLieHuaKeLong;

public class Test {
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.setName("zhangsan");
        Inner inner = new Inner();
        inner.setName("inner");
        outer.setInner(inner);
        Outer instance = outer.getInstance();
        inner.setName("inner-copy");
        instance.setName("lisi");
        System.out.println(instance);
        System.out.println(outer);
    }
}

结果

                                                

【SCI一区复现】基于配电网韧性提升的应急移动电源预配置动态调度(下)—MPS动态调度(Matlab代码实现)内容概要:本文档围绕“基于配电网韧性提升的应急移动电源预配置动态调度”主题,重点介绍MPS(Mobile Power Sources)动态调度的Matlab代码实现,是SCI一区论文复现的技术资料。内容涵盖在灾害或故障等极端场景下,如何通过优化算法对应急移动电源进行科学调度,以提升配电网在突发事件中的恢复能力与供电可靠性。文档强调采用先进的智能优化算法进行建模求解,并结合IEEE标准测试系统(如IEEE33节点)进行仿真验证,具有较强的学术前沿性工程应用价值。; 适合人群:具备电力系统基础知识Matlab编程能力,从事电力系统优化、配电网韧性、应急电源调度等相关领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①用于复现高水平期刊(SCI一区、IEEE顶刊)中关于配电网韧性与移动电源调度的研究成果;②支撑科研项目中的模型构建与算法开发,提升配电网在故障后的快速恢复能力;③为电力系统应急调度策略提供仿真工具与技术参考。; 阅读建议:建议结合前篇“MPS预配置”内容系统学习,重点关注动态调度模型的数学建模、目标函数设计与Matlab代码实现细节,建议配合YALMIP等优化工具包进行仿真实验,并参考文中提供的网盘资源获取完整代码与数据。
一款AI短视频生成工具,只需输入一句产品卖点或内容主题,软件便能自动生成脚本、配音、字幕特效,并在30秒内渲染出成片。 支持批量自动剪辑,能够实现无人值守的循环生产。 一键生成产品营销与泛内容短视频,AI批量自动剪辑,高颜值跨平台桌面端工具。 AI视频生成工具是一个桌面端应用,旨在通过AI技术简化短视频的制作流程。用户可以通过简单的提示词文本+视频分镜素材,快速且自动的剪辑出高质量的产品营销泛内容短视频。该项目集成了AI驱动的文案生成、语音合成、视频剪辑、字幕特效等功能,旨在为用户提供开箱即用的短视频制作体验。 核心功能 AI驱动:集成了最新的AI技术,提升视频制作效率质量 文案生成:基于提示词生成高质量的短视频文案 自动剪辑:支持多种视频格式,自动化批量处理视频剪辑任务 语音合成:将生成的文案转换为自然流畅的语音 字幕特效:自动添加字幕特效,提升视频质量 批量处理:支持批量任务,按预设自动持续合成视频 多语言支持:支持中文、英文等多种语言,满足不同用户需求 开箱即用:无需复杂配置,用户可以快速上手 持续更新:定期发布新版本,修复bug并添加新功能 安全可靠:完全本地本地化运行,确保用户数据安全 用户友好:简洁直观的用户界面,易于操作 多平台支持:支持Windows、macOSLinux等多个操作系统
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值