深拷贝 浅拷贝 深克隆 浅克隆

news/2024/7/7 21:56:18

深拷贝和浅拷贝:

浅拷贝只是拷贝对象的引用地址,两个引用地址指向的对象还是同一个,修改其中一个,另一个也会随之改变,因为这个引用地址指向的对象压根是同一个

而深拷贝是将对象和值都拷贝过来,形成一个新的对象,两者之间是独立的两个对象

在Java中,深拷贝又有两种实现形式:深克隆和浅克隆。

clone方法是Object类中的一个被protected和native修饰的方法,被native就代表它的实现源码是用c++实现的,只不过是我们无法去修改它的代码罢了。

为子类提供可以重写的clone()方法,目的是实现对象的浅克隆和深克隆

克隆的原理

在堆内存中新开辟一段空间,然后把被克隆对象的属性和方法赋值一份到新开辟的空间里面(副本)。

浅克隆

对于基本数据类型而言,是复制其的副本到新开辟的空间里面

对于引用数据类型而言,只是复制了引用的地址,并没有开辟新的空间,新的空间里面的引用和被克隆的里面的引用都指向于同一个空间

浅克隆的实现步骤

a 实现cloneable接口,这个是判断能否克隆的条件
b 重写Clone方法,建议采用如下所示的写法
public class Hello implements Cloneable{
    String str="hello";
    public Object clone() {
        Object cloneObject=null;
        try {
            cloneObject=super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return cloneObject;
    }

浅克隆存在一个问题:只能克隆对象主体,不能克隆引用着的属性对象,两个对象的关联引用对象仍然是同一个,解决办法是将属性对象的类也实现Cloneable接口,重写clone()方法,当引用对象过多或出现嵌套引用时,这种方法特别操蛋。所以,《java核心技术卷》中不推荐这种克隆。

深克隆

实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆

对于基本数据类型而言,是复制其的副本到新开辟的空间里面

对于引用数据类型而言,并不是复制了引用的地址,而是开辟了一个新的引用对象的空间,并把引用地址里面的属性和方法拷贝一份到新的引用对象的空间中,此时克隆对象里面的引用就指向于这个新的空间

public class MyUtil {
    private MyUtil() {
        throw new AssertionError();
    }
    @SuppressWarnings("unchecked")
    public static <T extends Serializable> T clone(T obj)
                                  throws Exception {
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bout);
        oos.writeObject(obj);
        ByteArrayInputStream bin =
                    new ByteArrayInputStream(bout.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bin);
        return (T) ois.readObject();
        // 说明:调用ByteArrayInputStream
        //或ByteArrayOutputStream对象的close方法没有任何意义
        // 这两个基于内存的流只要垃圾回收器清理对象就能够释放资源,
        //这一点不同于对外部资源(如文件流)的释放
    }
}

public static void main(String[] args) {
        try {
            Person p1 = new Person("郭靖", 33,
                              new Car("Benz", 300));
            Person p2 = MyUtil.clone(p1);   // 深度克隆
            p2.getCar().setBrand("BYD");
            // 修改克隆的Person对象p2关联的汽车对象的品牌属性
            // 原来的Person对象p1关联的汽车不会受到任何影响
            // 因为在克隆Person对象时其关联的汽车对象也被克隆了
            System.out.println(p1);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


http://lihuaxi.xjx100.cn/news/1490624.html

相关文章

交互设计原则:定义交互框架 优漫动游

1&#xff09;定义产品外形因素&#xff0c;你要设计的是什么产品&#xff1f;研究用户将投入多大的注意力和产品互动&#xff0c;产品的行为将会对用户投入的注意力做出如何的反应&#xff1b; 2&#xff09;定义功能和数据元素&#xff1b; 3&#xff09;决定功能组和层次…

LeetCode 面试题 02.03. 删除中间节点

文章目录 一、题目二、C# 题解 一、题目 若链表中的某个节点&#xff0c;既不是链表头节点&#xff0c;也不是链表尾节点&#xff0c;则称其为该链表的「中间节点」。 假定已知链表的某一个中间节点&#xff0c;请实现一种算法&#xff0c;将该节点从链表中删除。 例如&#x…

ACE 服务和配置设计维度

服务器提供给客户端的一组功能称为服务。在网上能够获取到常见的服务包括: Web内容解索服务。Castanet、Citrix这样的软件发布服务。电子邮件已经网络新闻的传输服务远程机器上的文件访问服务网络时间的同步,也就是NTP服务支付处理 服务RealPlayer或者QuickTime之类的音频/视频…

自定义Chronometer实现定时器

概述 自定义Chronometer实现定时器,引用方便&#xff0c;操作简单。 详细 前言 在Android开发过程中&#xff0c;计时控件是经常回使用到的&#xff0c;在Android控件库中有一个能快捷实现计时功能的控件&#xff0c;它就是Chronometer&#xff0c;今天我们基于它自定义实现…

SNN论文总结

Is SNN a great work ? Is SNN a convolutional work ? ANN的量化在SNN中是怎么体现的&#xff0c;和threshold有关系吗&#xff0c;threshold可训练和这个有关吗&#xff08;应该无关&#xff09; 解决过发放不发放的问题。 Intuation SNN编码方式 Image to spike patter…

Kuka机器人设计通用码垛程序

假设需要一个码垛程序, 从输送线抓到托盘, 托盘每层4个, 需要码5层, 可以用以下程序架构设计: 1, 再config中定义层数cengshu , 每层码垛的个数(码垛的次数)cishu , 每层的高度levelHeight , 码垛放置点的集合putPoint[,] ,预放点1集合prePut1[,], 预放点2集合prePut2[,] DEC…

国际站腾讯云容器镜像服务介绍!!

腾讯云容器镜像服务&#xff1a; 腾讯云的容器镜像服务Tencent Cloud Container Registry&#xff08;TCR&#xff09;旨在为开发者和企业供给高效、安全的容器镜像办理和存储平台&#xff0c;以处理容器镜像的保管、分发和办理问题。容器镜像是一种轻量级、可移植的软件包&…

【Python】python 打印本地代理

前言 在 Python 中&#xff0c;如果需要访问被墙的网站或者需要隐藏本机 IP 地址&#xff0c;可以通过使用代理服务器来实现。本文将介绍如何打印本地代理的方法&#xff0c;并提供相应的代码和实例。 一、什么是代理服务器 代理服务器&#xff08;Proxy Server&#xff09;是…