简单理解浅克隆和深克隆

简介: 简单理解浅克隆和深克隆

定义

浅克隆(Shadow Clone): 拷贝对象时仅仅拷贝对象本身,而不拷贝对象包含的引用指向的对象;对于数据类型是基本数据类型的成员变量,会直接进行值传递,也就是将该属性值复制一份给新的对象。

image.png

深克隆(Deep Clone): 将原型对象中所有类型,无论是值类型还是引用类型,都复制一份给克隆对象。

image.png

浅克隆的实现:

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Monkey implements Cloneable {
    private String name;
    private int age;

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


    public static void main(String[] args) throws CloneNotSupportedException {
        Monkey monkey1 = new Monkey("大明", 10);
        Monkey monkey2 = (Monkey) monkey1.clone();

        System.out.println(monkey1);
        System.out.println(monkey2);
    }
}

输出结果:
image.png

浅克隆存在弊端: 由于基本数据类型是直接存储在栈内存中的,而引用数据类型,则仅仅是把地址存储在栈内存中,真正的数据是存储在堆内存中的,赋值操作时,仅仅把地址进行了赋值。这样就会存在两个对象的成员变量同时指向一个实例,这种情况下,在对一个对象中的该成员变量进行修改会影响到另一个对象的该成员变量值。
例如:

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Park implements Cloneable {

    private String name;
    private Monkey monkey;


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


    public static void main(String[] args) throws CloneNotSupportedException {
        Monkey monkey1 = new Monkey("大明", 10);
        Park park1 = new Park("金山动物园", monkey1);
        Park park2 = (Park) park1.clone();

        System.out.println("修改引用变量前:>>>>park1>>>>" + park1);
        System.out.println("修改引用变量前:>>>>park2>>>>" + park2);

        Monkey monkey2 = park2.getMonkey();
        monkey2.setName("二明");
        monkey2.setAge(9);

        System.out.println("修改引用变量后:>>>>park1>>>>" + park1);
        System.out.println("修改引用变量后:>>>>park2>>>>" + park2);
    }
}

输出:
image.png

这里看到,修改了park2中的monkey2变量,导致park1中的monkey1变量也发生了变化。所以这里引入了深克隆。即要克隆类的基本数据类型,以及所有非基本数据类型的属性。

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Park implements Cloneable {

    private String name;
    private Monkey monkey;


    @Override
    protected Object clone() throws CloneNotSupportedException {
        /**
         * 主要是这里
         */
        Park park = (Park)super.clone();
        park.setMonkey((Monkey) park.getMonkey().clone());
        return park;
    }


    public static void main(String[] args) throws CloneNotSupportedException {
        Monkey monkey1 = new Monkey("大明", 10);
        Park park1 = new Park("金山动物园", monkey1);
        Park park2 = (Park) park1.clone();

        System.out.println("修改引用变量前:>>>>park1>>>>" + park1);
        System.out.println("修改引用变量前:>>>>park2>>>>" + park2);

        Monkey monkey2 = park2.getMonkey();
        monkey2.setName("二明");
        monkey2.setAge(9);

        System.out.println("修改引用变量后:>>>>park1>>>>" + park1);
        System.out.println("修改引用变量后:>>>>park2>>>>" + park2);
    }
}

输出结果:
image.png

这里简单的示例帮助理解深克隆和浅克隆。

深克隆方式

1、实现Cloneable接口

2、使用JDK自带的字节流实现深克隆

3、使用第三方工具类实现深克隆,比如Apache Commons Lang

4、使用Json工具实现深克隆,比如Gson、FastJSON,使用JSON.pasre和JSON.stringify。

相关文章
|
SQL 数据库
达梦(DM) SQL数据及字符串操作
继续讲述DM数据库Sql操作
|
机器学习/深度学习 人工智能 自然语言处理
DeepRant:一款专为国际游戏玩家设计的翻译工具,一键翻译聊天对话,无需切出游戏
专为游戏玩家设计的多语言快捷翻译工具,支持多种翻译模式和主流语言,基于Tauri和React开发。
1182 12
DeepRant:一款专为国际游戏玩家设计的翻译工具,一键翻译聊天对话,无需切出游戏
ly~
|
并行计算 算法 API
SDL 图形库优化对硬件要求有何变化
SDL(Simple DirectMedia Layer)图形库是一个跨平台的多媒体库,适用于多种操作系统和设备。优化后的SDL 2.0对硬件的要求有所提升,特别是显卡性能。优化包括提高渲染效率、利用硬件加速功能、支持高效解码算法等,以增强图形处理能力和流畅度。同时,优化后的SDL对输入设备的交互体验要求更高,需确保键盘、鼠标、触摸屏等设备的顺畅操作。尽管如此,SDL仍保持良好的兼容性,能在较低配置的硬件上运行,只是性能表现会有所差异。
ly~
1056 4
|
程序员
中国程序员的挑战与困境:行业现状深度解析
在中国,程序员作为技术行业的中坚力量,他们面临的挑战和困境值得关注。这些挑战不仅影响着程序员的个人发展,也关系到整个技术行业的进步。本文将探讨中国程序员面临的一些主要问题,并分析这些问题背后的原因,同时探讨可能的解决方案。
401 1
|
XML 编解码 文字识别
PyMuPDF 1.24.4 中文文档(八)(4)
PyMuPDF 1.24.4 中文文档(八)
885 1
|
存储 分布式计算 Hadoop
ClickHouse(01)什么是ClickHouse,ClickHouse适用于什么场景
ClickHouse是一款高性能的列式存储OLAP数据库,由俄罗斯的Yandex公司开发,用于在线分析处理(OLAP)。它提供秒级大数据查询,适用于商业智能、广告流量等领域。ClickHouse速度快的原因包括列式存储、数据压缩、向量化执行和多线程分布式处理。然而,它不支持事务,不适合OLTP操作。相比Hadoop生态中的查询引擎,ClickHouse在大量数据查询上表现出色。一系列的文章详细介绍了ClickHouse的各个方面,包括安装、表引擎和使用场景。
2717 2
ClickHouse(01)什么是ClickHouse,ClickHouse适用于什么场景
|
机器学习/深度学习 运维 分布式计算
阿里云大数据ACA及ACP复习题(491~500)
本人备考阿里云大数据考试时自行收集准备的题库,纯手工整理的,因为是纯手工整理解析所以可能出现答案打错的情况,题库是能够覆盖到今年7月份,应该是目前最新的,发成文章希望大家能一起学习,不要花冤枉钱去买题库背了,也希望大家能够顺利通关ACA和ACP考试(自己整理解析也需要时间,可能有更新不及时的情况哈)
|
消息中间件 Kafka 测试技术
Kafka、RabbitMQ、RocketMQ发送小消息性能对比
引言 分布式系统中,我们广泛运用消息中间件进行系统间的数据交换,便于异步解耦。现在开源的消息中间件有很多,前段时间我们自家的产品 RocketMQ (MetaQ的内核) 也顺利开源,得到大家的关注。那么,消息中间件性能究竟哪家强? 带着这个疑问,我们中间件测试组对常见的三类消息产品(Kafka、
15089 230
|
Java Android开发 C++
JNI中如何实现日志功能
JNI中如何实现日志功能
373 0

热门文章

最新文章