List的clone()方法

Java对象深拷贝详解(List深拷贝) Java对象深拷贝详解(List深拷贝) 解决List复制到新的List时,新的List值错误问题 阅读详情

概述

在查看ArrayList和LinkedList的源码的时候,比较困惑的就是clone()方法。
我们都知道在Object里clone()方法是浅拷贝(浅拷贝的定义:只clone对象本身,不clone对象里的字段),那在集合里它到底是深拷贝还是浅拷贝呢?
我们看一下ArrayList.clone()源码:

public Object clone() {
            try {
                @SuppressWarnings("unchecked")
                    ArrayList<E> v = (ArrayList<E>) super.clone();
                v.elementData = Arrays.copyOf(elementData, size);
                v.modCount = 0;
                return v;
            } catch (CloneNotSupportedException e) {
                // this shouldn't happen, since we are Cloneable
                throw new InternalError();
            }
        }

我们可以看到,返回的是一个全新的ArrayList实例对象,但是其elementData,也就是存储数据的数组,存储的对象还是指向了旧的ArrayList存储的那些对象。也就是ArrayList这个类实现了深拷贝,但是存储的对象还是浅拷贝。
我们验证一下:

import java.util.ArrayList;
import java.util.Iterator;

public class Main {

    static Main ins = new Main();

    //内部类
    class Node{
        int val;
        Node(int val){
            this.val = val;
        }

        public void setVal(int val) {
            this.val = val;
        }

        @Override
        public String toString() {
            return "Node [val=" + val + "]";
        }

    }

    public static void main(String[] args) {


        ArrayList<Node> list = new ArrayList<Node>();
        list.add(ins.new Node(2));
        list.add(ins.new Node(11));
        list.add(ins.new Node(44));

        ArrayList<Node> newlist = (ArrayList<Node>) list.clone();

        //修改list中元素之前的newlist
        for(Node k : newlist){
            System.out.println(k);
        }
        //修改list中index为0的对象的值为90
        list.get(0).setVal(90);
        System.out.println("--------------------------------");

        //修改后newlist,index为0的对象也变化了
        for(Node k : newlist){
            System.out.println(k);
        }
    }
}

其运行结果为:

Node [val=2]
Node [val=11]
Node [val=44]
--------------------------------
Node [val=90]
Node [val=11]
Node [val=44]

我们可以看到,通过改变旧的list存储的对象的值,新的list存储的对象的值也发生了改变。说明其指向了同一个对象。
这里写图片描述

那么会不会list和newlist其实指向同一个对象呢?
执行System.out.println("list==newlist?:"+(list==newlist));
其结果为:list==newlist?:false
说明list和newlist指向两个不同的内存地址空间

同样的,LinkedList的clone()也是实现一个浅复制

1011     /**
1012      * 父类克隆方法
1013      */
1014     @SuppressWarnings("unchecked")
1015     private LinkedList<E> superClone() {
1016         try {
1017             return (LinkedList<E>) super.clone();
1018         } catch (CloneNotSupportedException e) {
1019             throw new InternalError(e);
1020         }
1021     }
1022 
1023     /**
1024      * 克隆,浅拷贝
1025      *
1026      * @return a shallow copy of this {@code LinkedList} instance
1027      */
1028     public Object clone() {
1029         LinkedList<E> clone = superClone();
1030 
1031         // 链表初始化
1032         clone.first = clone.last = null;
1033         clone.size = 0;
1034         clone.modCount = 0;
1035 
1036         // 插入结点
1037         for (Node<E> x = first; x != null; x = x.next)
1038             clone.add(x.item);
1039         // 返回克隆后的对象引用
1040         return clone;
1041     }

那么要怎么实现一个ArrayList的深拷贝呢?
通过实现对象类的clone方法。

import java.util.ArrayList;
import java.util.Iterator;

public class Main {

    static Main ins = new Main();
    class Node{
        int val;
        Node(int val){
            this.val = val;
        }

        public void setVal(int val) {
            this.val = val;
        }

        @Override
        public String toString() {
            return "Node [val=" + val + "]";
        }
        //在对象中重写clone()方法
        @Override
        public Node clone(){
            Node node = new Node(this.val);
            return node;
        }
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        ArrayList<Node> list = new ArrayList<Node>();
        list.add(ins.new Node(2));
        list.add(ins.new Node(11));
        list.add(ins.new Node(44));

        //深拷贝
        ArrayList<Node> listCopy = new ArrayList<>();
        for(Node node:list){
            listCopy.add(node.clone());
        }
        //移除且不修改
        listCopy.get(0).setVal(100);
        System.out.println(list);
        System.out.println(listCopy);

    }
}

结果为:

[Node [val=2], Node [val=11], Node [val=44]]
[Node [val=100], Node [val=11], Node [val=44]]
Java 中 List 的 N 种深拷贝方式 不同的深拷贝方法各有优缺点,选择合适的方法取决于具体的应用场景。使用是实现深拷贝最直接的方式。使用 Stream API 提供了更简洁的语法。好啦,今天的分享就到这里。我们下次再见!👋🏻。 阅读详情

相关推荐

便携式水下动态实时视频色彩还原设备,一键快速实现对水下偏色视频和图像的色彩还原处理

便携式水下动态实时视频色彩还原,一键快速对水下图像进行色彩校正,清晰度提升和亮度均衡处理,为水下资源勘探和科学考古,海洋生态环境监测,水下机器作业等应用提供有力的协助

weixin_43518680的博客 633

java复制list_Java克隆复制一个新的List集合的方法

在Java开发中,有时候我们为了源List集合的数据不被修改,如果采用类似“new_list = old_list”这种形式来复制克隆一个新的List集合是绝对不行的,所以我们得采用下面的三种方法来复制一个新的List集合。Java克隆复制ArrayList等List集合的方法一:Java中克隆复制一个List可以在创建List对象时通过将源List集合以参数的形式传入即可,代码如下:import...

weixin_33609486的博客 2万+

代码生成 | 安时积分法模型搭建

安时积分法是电池电量计量最基础的方法,今天我们用simulink建模的方式做一个安时积分模型,从而更好地理解安时积分的思想也掌握建模的基础操 ​新建文件 打开MATLAB启动simulink新建一个模型文件 定义变量 和手写代码一样,先定义几个后面要用到的变量,在simulink建模时新建变量用Data Store Memory模块。双击填入要定义的变量名,然后在signal attributes赋初值 如此方法新建四个变量current(电流)初值1000mA、tatol_cap(总容量

ningvay的博客 1万+

Java克隆复制一个新的List集合的方法

在Java开发中,有时候我们为了源List集合的数据不被修改,如果采用类似“new_list = old_list”这种形式来复制克隆一个新的List集合是绝对不行的,所以我们得采用下面的三种方法来复制一个新的List集合。 Java克隆复制ArrayList等List集合的方法一: Java中克隆复制一个List可以在创建List对象时通过将源List集合以参数的形式传入即可,代码如下:importjava.util.ArrayList; importjava.util.Arrays; importjav

web15285868498的博客 6458

Stata实战:5步搞定PSM倾向得分匹配(附完整代码与常见报错解决)

本文详细介绍了使用Stata进行PSM(倾向得分匹配)的5步实战流程,包括数据预处理、模型构建、匹配算法选择、匹配质量诊断和结果解释。提供完整代码示例和常见报错解决方案,帮助研究者高效完成实证分析,提升匹配成功率。

weixin_29214559的博客 592

codemirror6 制作markdown编辑器(源码模式)

总体上感觉能用,但是不怎么友好,官方文档有点散乱,而且关键字高亮功能是独立出去的,去官方文档找半天,也没找到怎么改。EditorView.theme可以往EditorView模块中修改CSS的样式,从而影响编辑器的样式展示。"### 测试\n\n```javascript\nlet x = 'y'\n```"这个插件中的markdown语法的高亮样式。//这里指定markdown中代码块使用的解析扩展。开头的class样式,并且还需要在选择器前面添加。//markdown语言解析扩展。

qq_43203949的博客 1784

如何巧妙的使用ArrayList的Clone方法

一、ArrayList的Clone方法的源码 返回一个Object对象,所以在使用此方法的时候要强制转换。 ArrayList的本质是维护了一个Object的数组,所以克隆也是通过数组的复制实现的,属于浅复制。 public Object clone() { try { @SuppressWarnings("unchec...

weixin_33847182的博客 1020

PostgreSQL使用 pg_rman物理备份搭建流复制备库(streaming replication standby)

摘要:使用pg_rman备份搭建PostgreSQL流复制备库 本文详细介绍了利用pg_rman工具快速搭建PostgreSQL流复制备库的完整流程。该方法结合物理备份的高效性和流复制的实时性,特别适合大型数据库环境。主要内容包括:主库上的pg_rman安装配置、全量备份操作;备份文件传输至备库;备库数据目录准备及恢复;流复制参数配置;以及最终的启动验证步骤。文章还提供了架构示意图和关键配置示例,并包含常见问题排查建议,如备库无法启动或复制卡顿情况的处理方法。整个流程强调通过.pgpass文件管理密码的安全

liumangtuzi888的博客 1169

java list的 clone_Java ArrayList clone()方法

Java ArrayList clone()方法java.util.ArrayList.clone() 返回此ArrayList实例的浅表复制。1 语法public Object clone()2 参数无3 返回值返回此ArrayList实例的副本。4 示例package com.yiidian;/*** 一点教程网: http://www.yiidian.com*//*** java.util....

weixin_29923451的博客 2076

【制作100个unity游戏之22】3DRPG游戏开发01——项目的设置和导入及渲染管线的安装修复

如果你现在存在一些疑惑unity导入素材为什么是粉紫色的?表示他没有适配我们的URP通用渲染管线,要如何适配呢?素材渲染错误丢失要如何解决?如果你有上面3个任意的问题,那这篇文章同样适合你,我将手把手教你如何安装修复渲染管线,看完你就了解了!在Unity中,他们都是渲染管线,它们的主要区别在于性能和功能。LWRP是早期版本的URP,它专门为移动设备和低端PC设计,旨在提供更高的性能。它使用基于顶点的光照和简化的后处理效果,可以在更低的硬件要求下运行。

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 2430

jdbc从入门到精通(全)

前言 Java语言连接数据库(Java DataBase Connectivity) 面向接口/抽象编程(降低程序的耦合度,提高程序的扩展力)类似多态机制

码农研究僧的博客 1759

java list的 clone,Java LinkedList对象的clone()方法和示例

LinkedList对象clone()方法包java.util.Collection中提供了此方法,在这里Collection是一个接口。此方法用于创建链接列表的重复副本或浅表副本。在这种方法中,我们需要两个相同类型的对象,并将一个对象复制到另一个对象中。此方法不返回异常。语法:Objectclone(){}参数:此方法不接受任何参数。返回值:该方法的返回类型为Object,这意味着该方法在执...

weixin_42507981的博客 426

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

java list的 clone_Java.util.ArrayList.clone()方法实例

全屏java.util.ArrayList.clone()返回此ArrayList实例的浅表副本(即本身是不可复制的元素)。声明以下是java.util.ArrayList.clone()方法的声明publicObjectclone()参数NA返回值这个方法返回当前ArrayList实例的一个副本。异常NA例子下面的示例演示java.util.Arraylist.clone()方法的用法。p...

weixin_39787345的博客 234

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

java list的 clone_Java中的LinkedList clone()方法:Java.util.LinkedList.clone - Break易站

句法:LinkedList.clone()参数:此方法不带任何参数。返回值:该函数返回链接列表实例的副本。Java.util.LinkedList.clone()方法的示例// Java code to illustrate clone() methodimport java.io.*;import java.util.LinkedList;public class LinkedListDemo ...

weixin_31488273的博客 138

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Java List中内容的深复制

探讨如何对Java List中内容的深复制,结论是把List中的对象进行clone(),或者序列化的方法可以达到目的,而把List本身(对象的容器)进行clone()是不行的。

我的博客 5968

Java、C#将一个List赋值给另一个List的方式(及直接用=等号赋值会出现的坑)

#声明和实例化 声明:ArrayList a, 仅仅只是声明了一个list变量,其未来作用相当于C++中的引用变量,亦或者相当于一个对象块的索引,但并未为其分配具体的完整的对象所需要的内存空间,其所分配的空间仅仅只是"a"变量所需空间; 实例化:实例化的过程是为对象分配完整的所需内存空间。此时,对象a才是该list的一个实例,然后将分配的内存地址返回给定义的变量“a”; #java的实例化 ...

大头之家 8301

clone() java 简单的复制

Java的复制有的 deepcopy 和 shapecopy 之分,这里简单的采用shapecopy 的 clone ( ) 方法, 但是指向的是同一个对象, 关于对象的问题,这里不做展开: // processing 软件  import java.util.*; LinkedList<Integer> path = new LinkedList<Int...

weixin_30622181的博客 67

java 如何获取得到两个list中不同的数据

如何移除两个List中相同的数据,比如说现在有groupNameList 跟 defaulGrouptNameList两个字符串数组:       1、先复制,clone()       ArrayList a = (ArrayList) groupNameList.clone();       2、再移除,remove()       a.removeAll(Arrays

AlanBoon希望能够帮助到你! 6799

List使用add方法添加的是对象的引用,而不是对象的拷贝。

今天做八皇后算法的时候发现list保存的所有的解都是7开头的,而且完全一样。调试了好久才发现可能是引用的问题,特别是static修饰的变量容易出现这个问题,亏我前几天面试还被问到了java的引用问题。 解决办法是调用list 的add方法体里使用对象的clone方法 list.add(chars.clone()); 或者new 一个新对象 如下: List<String[]> li...

qq_43047165的博客 3933

java将一个List赋值给另一个List的4种方法 常见问题

声明:ArrayList a, 仅仅只是声明了一个list变量,其未来作用相当于C++中的引用变量,亦或者相当于一个对象块的索引,但并未为其分配具体的完整的对象所需要的内存空间,其所分配的空间仅仅只是"a"变量所需空间; 实例化:实例化的过程是为对象分配完整的所需内存空间。此时,对象a才是该list的一个实例,然后将分配的内存地址返回给定义的变量“a”; #java的实例化 1. 使用...

qq_36457702的博客 1960

list 赋值给 另外的 list

list 赋值给 另外的 list 描述 : 直接用 = 号赋值是不行的, 这样是引用传递,对副本操作也会改变原本的内容. 解决 : 1. ArrayList B = new ArrayList<> (A); 2. ArrayList B = A.clone(); 3. ArrayList B = new ArrayList(); B.addAll(A); ...

Gronbu1的博客 327

list通过clear清空进行,会将之前通过“add”或“=”关联的对象同时进行变更。[问题解决]

List<String> A= new ArrayList<>(); A.add("1"); List<String> B = new ArrayList<>(); List<List<String>> C = new ArrayList<>(); B = A; C.addAll(A); A.clear(); ...

一只小蚂蚁的自白 1413

【053期】面试官问:说说 List 复制深拷贝和浅拷贝的用法与区别?

造成的后果就是,改变B的同时也会改变A,因为改变B就是改变B所指向地址的内容,由于A也指向同一地址,所以A与B一起改变。

2501_90252464的博客 588

一些不靠谱的java.util.List深复制方法

之前探讨过Java数组的深复制问题,现在来说说&lt;一些不靠谱的java.util.List深复制方法&gt;。为什么不说&lt;靠谱的 深复制方法&gt;呢?因为在寻找探索&lt;靠谱的深复制方法&gt;的过程中,我发现了这些不靠谱的方法,写下来是希望给自己和他人提个醒,不要犯这 样的错误。   这是下面要频繁使用的一个JavaBean   Java代码   cla...

zzc1684的博客 214

java 集合 副本,如何使ArrayList对象的副本是List的类型?

I studied Java is pass object reference by value, and in order to make a local copy of an object, I can either do clone() or copy-constructor. I also looked at deep/shallow copy as well as several pos...

weixin_30273229的博客 283
上一篇: ArrayList源码分析
下一篇: LinkedList源码分析
HY_Chan
博客等级 码龄10年 54粉丝 60原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值