Java对象深拷贝详解(List深拷贝)

news2024/11/21 1:28:19

1、Java中拷贝的概念

在Java语言中,拷贝一个对象时,有浅拷贝与深拷贝两种

浅拷贝:只拷贝源对象的地址,所以新对象与老对象共用一个地址,当该地址变化时,两个对象也会随之改变。

深拷贝:拷贝对象的所有值,即使源对象发生任何改变,拷贝的值也不会变化。

在User类的基础上,介绍两种浅拷贝案列

User类:

@Data
public class User {
    private String name;
    private Integer age;
}

案列①:普通对象的浅拷贝

package com.shuizhu.study;
//浅拷贝案例1
public class Study01 {
    public static void main(String[] args) {
        User user1 = new User();
        user1.setName("张三");
        user1.setAge(18);
        User user2 = user1;
        System.out.println("user1未改变前,user2的名字为:" + user2.getName());
        user1.setName("李四");
        System.out.println("user1未改变前,user2的名字为:" + user2.getName());
    }
}

结果:改变user1后,user2的值也随之变化

 

案列②:List浅拷贝(这也是我们平时项目中,经常遇到的情况)

package com.shuizhu.study;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

//Java浅拷贝案列2
public class Study02 {
    public static void main(String[] args) {
        List<User> list1 = new ArrayList<>();
        User user1 = new User();
        user1.setName("张三");
        user1.setAge(18);
        User user2 = new User();
        user2.setName("李四");
        user2.setAge(19);
        list1.add(user1);
        list1.add(user2);
        //TODO 以下是开发中,经常发生的浅拷贝
        //方式1:通过new ArrayList方式,把list01拷贝给list02
        List<User> list2 = new ArrayList<>(list1);
        System.out.println("list1未改变前,list2的结果为:" + list2);

        //方式2:通过addAll方法,把list01拷贝给list02
        List<User> list3 = new ArrayList<>();
        list3.addAll(list1);
        System.out.println("list1未改变前,list3的结果为:" + list3);

        //方式3:通过stream流的方式,把list01拷贝给list02
        List<User> list4 = list1.stream().collect(Collectors.toList());
        System.out.println("list1未改变前,list4的结果为:" + list4);

        //改变list1集合中的user1对象
        System.out.println("--------------------------------------------");
        user1.setName("老六");
        user1.setAge(78);

        System.out.println("list1改变后,list2的结果为:" + list2);
        System.out.println("list1改变后,list3的结果为:" + list3);
        System.out.println("list1改变后,list4的结果为:" + list4);
    }
}

结果:对List的3种拷贝,其实都是浅拷贝,当源集合中对象发生改变时,新的List也会随之变化

2、常见的深拷贝方式

  1. 构造函数方式(new的方式)
  2. 重写clone方法
  3. Apache Commons Lang序列化
  4. Gson序列化
  5. Jackson序列化

2.1、构造函数方式

这种方式就是创建一个新的对象,然后通过源对象的get方法与新对象set方法,把源对象的值复制新对象,这里就不再演示了。

缺点:在拷贝的对象数量较少时,可以使用,但是对象数量过多时,会大大增加系统开销,开发中应避免使用。

2.2、重写clone方法

步骤:

1>需要拷贝对象的类,去实现Cloneable接口

2>重写clone方法

3>使用"对象.clone()"的方式进行拷贝

根据上面的案列,进行对应的改造:

首先是User实体类 ,如下:

@Data
public class User implements Cloneable{
    private String name;
    private Integer age;

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

改造案列①:

package com.shuizhu.study;
//Java深拷贝案列
public class Study03 {
    public static void main(String[] args) throws CloneNotSupportedException {
        User user1 = new User();
        user1.setName("张三");
        user1.setAge(18);
        User user2 = user1.clone();
        System.out.println("user1未改变前,user2的名字为:" + user2.getName());
        user1.setName("李四");
        System.out.println("user1未改变前,user2的名字为:" + user2.getName());
    }
}

结果:当user1改变后,user2的值不会改变

改造案列2:

package com.shuizhu.study;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

//Java深拷贝案列
public class Study04 {
    public static void main(String[] args) {
        List<User> list1 = new ArrayList<>();
        User user1 = new User();
        user1.setName("张三");
        user1.setAge(18);
        User user2 = new User();
        user2.setName("李四");
        user2.setAge(19);
        list1.add(user1);
        list1.add(user2);
        //TODO 以下是开发中,经常发生的浅拷贝
        //方式1:通过new ArrayList方式,把list01拷贝给list02
        List<User> list2 = new ArrayList<>();
        list1.forEach(user->{
            try {
                list2.add(user.clone());
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
        });
        System.out.println("list1未改变前,list2的结果为:" + list2);
        
        //改变list1集合中的user1对象
        System.out.println("--------------------------------------------");
        user1.setName("老六");
        user1.setAge(78);

        System.out.println("list1改变后,list2的结果为:" + list2);
    }
}

结果:list1中的每个对象通过clone()添加list2中,当list1中的对象改变时,list2不会改变

2.3 、Apache Commons Lang序列化

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/76724.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一起学习用Verilog在FPGA上实现CNN----(一)总体概述

1 总体概述 为避免闭门造车&#xff0c;找一个不错的开源项目&#xff0c;学习在FPGA上实现CNN&#xff0c;为后续的开发奠定基础 1.1 项目链接 大佬的开源项目链接&#xff1a; CNN-FPGA 链接跳转界面如下&#xff1a; 大佬的该项目已经发表论文&#xff0c;而且开源工程结…

Qt5.6.1移植海思Hi3521d(一)

系列文章目录 文章目录系列文章目录前言一、开发环境二、搭建环境1.准备2.海思SDK和交叉编译器安装2.测试交叉编译器一下3.安装tftp总结前言 上半年做个一个Qt移植海思芯片的程序&#xff0c;感觉差不多快忘记了&#xff0c;赶紧记录一下 一、开发环境 系统&#xff1a;Ubunt…

初学Python到月入过万最快的兼职途径(纯干货)

程序员小猴紫&#xff0c;不错过任何一次干赚钱干货 1.兼职薪资&#xff0c;附行哥工资单2.兼职门槛&#xff0c;附学习知识清单3.兼职途径&#xff0c;附入职考核过程4.我的兼职感受 答应小猴紫的第一篇赚钱干货推文来啦&#xff0c;行哥第一个在读书期间通过兼职赚到的10w收…

Web前端大作业—里约热内卢奥运会(html+css+javascript)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

产品经理 - 产品设计方法论需求分析部分

整体 – 产品设计方法论思维导图 个人整理&#xff0c;存在异议大家可以讨论下 需求分析方法论 需求分析为需求收集的延展&#xff0c;需求收集后即需进行需求分析&#xff0c;拆解需求后方可业务落地&#xff0c;此处我将其分为两步&#xff0c;一是主动发散型需求分析&am…

移动端项目(第十九课)Vite+Vant组件环境配置

常用到的环境配置时不我待(第十八课)项目环境搭建_星辰镜的博客-CSDN博客 在上面的环境的基础上加上下面的一下配置 Normalize.css: Make browsers render all elements more consistently. (necolas.github.io) 介绍 | Pinia 中文文档 (web3doc.top) Day.js 中文文档 - 2kB 大…

【Java版oj】day02排列子序列

目录 一、原题再现 二、问题分析 三、完整代码 一、原题再现 链接&#xff1a;排序子序列_牛客笔试题_牛客网 来源&#xff1a;牛客网 [编程题]排序子序列 热度指数&#xff1a;10105 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 32M&…

水果店引流活动推荐_分享水果店微信小程序制作步骤

试试做个小程序拯救你的店&#xff01;让你做出有效果的活动&#xff0c;每笔钱都花在刀刃上&#xff01; 第一&#xff0c;提升水果销量&#xff0c;降低损耗 用水果店小程序做拼团、砍价、秒杀活动&#xff0c;并讲原本卖不完的水果&#xff0c;做成果盘吸引客人注册会员。上…

Manufactoria介绍及各关卡解法

Manufactoria解法Manufactoria基本介绍解法RobotoastRoboManufactoria基本介绍 Manufactoria是一个以制造工厂为背景的程序设计游戏。在游戏中&#xff0c;玩家需要在有限的平面空间中巧妙地排布传送带&#xff0c;打点器与分支器&#xff0c;完成识别或改写特定模式的字符串的…

6.AOP之转账案例

数据准备 CREATE TABLE account (id int(11) NOT NULL,name varchar(100) NOT NULL,money decimal(7,2) NOT NULL,create_time datetime(6) NOT NULL,PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8;insert into account values(1,"steven",10000,"2022…

循环程序设计 乘法口诀表

凡是写循环程序 必须满足两个条件 一是存在相同的操作 二是有规律 对于乘法口诀表 我们都很熟悉 如下图是左下角的 探求一下 规律&#xff1a; 1 多个乘法 2 规律性 第一1行 1个乘法运算 1*1 第二2行 2个乘法运算 1*2 2*2 第三3行 3个乘法运算 1*3 2*3 3*3 第四4行 4个…

关于Linux的基础总结

关于Linux的基础总结 文章目录关于Linux的基础总结前言一、为什么Linux如此流行&#xff1f;1.原因2.Linux系统的版本二、Linux的基础命令1.目录结构2.文件命令1.ls2.pwd3.cd4.touch、mkdir5.cat、tail、head、tail、od、tee、more、less6.rm、cp、mv7.find、grep、xargs8.tar、…

voc To yolov5-6.1数据集格式转换

voc To yolov5-6.1数据集格式转换 已有的数据集操作第一步:划分训练集、验证集、测试集通过脚本文件(createImageSet.py)生成训练集和验证集本代码需要修改的地方:结果:第二步:vocToyolo1、Head_classes.json文件:Head_classes.json文件对应的代码:3、操作技巧:2、第二…

用Python画一个足球

文章目录前情提要先画六边形再画五边形前情提要 如果想优雅地绘制一个足球&#xff0c;那首先需要绘制正二十面体&#xff1a;用Python绘制正二十面体 其核心代码为 import numpy as np from itertools import product G (np.sqrt(5)-1)/2 def getVertex():pt2 [(a,b) fo…

【Flask框架】——07 request请求和 get请求 post请求

request参数 指定请求方式 在Flask中&#xff0c;可以定义路由默认的请求方式&#xff1a; 利用 methods 参数可以自己指定一个接口的请求方式 get方式&#xff1a;把请求参数放到为url的&#xff1f;后面&#xff0c;每个请求参数格式为&#xff1a;参数名参数值。参数之间…

全梯度下降算法、随机梯度下降算法、小批量梯度下降算法、随机平均梯度下降算法、梯度下降算法总结

一、常见梯度下降算法 全梯度下降算法(Full gradient descent&#xff0c;FGD&#xff09;随机梯度下降算法&#xff08;Stochastic gradient descent&#xff0c;SGD&#xff09;随机平均梯度下降算法&#xff08;Stochastic average gradient descent&#xff0c;SAGD&#…

12.9工作学习记录 课程统计 Echarts表格插件 Stream.map

课程统计接口要做的是 统计各个日期的用户观看人数 生成报表 sql就是根据日期分组 查出开始时间到结束时间这个区间范围内 每天有多少人观看 SELECT DATE(join_time) AS joinTime, COUNT(*) AS userCount FROM video_visitor <…

基于ServiceStage的微服务开发与部署(二)

目录 2.微服务开发与部署 2.1. 组织管理 2.2. 仓库授权 2.3. 微服务接入CSE 2.4. 基于源码构建软件包 2.5. 创建环境 2.6. 应用部署 2.7. 外网访问 2.微服务开发与部署 2.1. 组织管理 步骤 1 打开应用管理与运维平台控制台&#xff0c;在"软件中心"-"组织管理&q…

【QT开发笔记-基础篇】| 第五章 绘图QPainter | 5.4 点、线

本节对应的视频讲解&#xff1a;B_站_视_频 https://www.bilibili.com/video/BV1x14y1J7rn 完成了界面布局&#xff0c;以及添加了初始化数据&#xff0c;就可以开始真正绘制图形了 本节讲解如何绘制点、线 1. 基本点线的绘制 1.1 为 cboShape 关联信号槽 首先&#xff0c;…

NR 多天线传输过程 2- Scrambling -1

参考 《5G 无线系统设计与国际标准》 于威廉斯托林斯的《数据与计算机通信》 《south western university--Scrambling》 《Prof. Hitesh Dholakiya-- Scrambling》 前言 最近一次答辩&#xff0c;有同事问了LDPC 和 线性分组码有什么区别&#xff0c;当时只说出了应用场景…