java中的拷贝

1.Object中的clone方法

在Object中的clone方法是这样描述的,如下图(摘自jdk1.8 Object类clone):


Object类clone方法的描述

如果一个类没有实现Cloneable接口,如果调用对象.clone则会抛出CloneNotSupportedException异常。

public class Clone {
    private int a;
    String b = "123";
    public static void main(String[] args) throws CloneNotSupportedException {
        Clone clone = new Clone();
        Clone clone1 = (Clone) clone.clone();
        System.out.println();
    }
}
异常信息

下面我们对Clone类实现Cloneable接口

public class Clone implements Cloneable{
    private int a;
    private String b = "123";
    private Student c = new Student(1,"str");
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
    public static void main(String[] args) throws CloneNotSupportedException {
        Clone clone = new Clone();
        Clone clone1 = (Clone) clone.clone();
        System.out.println();
    }
}

执行结果如下:

实现Cloneable接口的结果

由上图可以看出,clone对象和clone1对象的内存地址是不一样的,表明确实重新开辟一个空间,而不是两个不同的引用指向同一个内存空间,但是可以看到两个对象中的成员变量c指向的是同一个对象,这表明
1.对于基本数据类型,是直接拷贝的(也可以理解为深拷贝)
2.对于引用数据类型,没有进行拷贝,是两个不同的引用指向了同一个对象
所以说我们修改clone对象的成员变量a不影响clone1对象的成员变量a

public class Clone implements Cloneable{
    private int a;
    private String b = "123";
    private Student c = new Student(1,"str");
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
    public static void main(String[] args) throws CloneNotSupportedException {
        Clone clone = new Clone();
        Clone clone1 = (Clone) clone.clone();
        clone.a = 1;
        System.out.println();
    }
}
修改clone对象的成员变量a后的执行结果

如果我们修改clone对象的成员变量c对象的中的a成员变量,则clone对象和clone1对象中都要改变

public class Clone implements Cloneable{
    private int a;
    private String b = "123";
    private Student c = new Student(1,"str");
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
    public static void main(String[] args) throws CloneNotSupportedException {
        Clone clone = new Clone();
        Clone clone1 = (Clone) clone.clone();
        clone.c.setA(123333);
        System.out.println();
    }
}
修改引用类型的成员变量执行结果

2.数组的拷贝

2.1 一维数组

对于基本数据类型的数组,使用clone方法是深拷贝

int[] array1 = new int[]{1,2,3};
int[] array2 = array1.clone();
array2[1] = 3;

在array2完成对array1的拷贝后,我们对array2中数组下标为1赋值为3,不影响array1中的值,执行结果如下:


基本数据类型数组的clone

对于引用数据类型的数组,使用clone方法是浅拷贝

Clone[] clones1 = new Clone[]{new Clone(),new Clone()};
Clone[] clones2 = clones1.clone();

执行结果如下:


引用数据类型数组的clone

可以看到两个引用是不同的对象,但是clones1指向对象的数组下标0和clones2指向对象的数组下标0是指向了同一个对象。

2.2 二维数组

对于基本数据类型的二维数组如int[][] arrays,因为java中没有二维数组的概念,只有数组的数组,所以二维数组arrays中存储的实际上是一维数组的引用。当调用clone函数时,是对这两个引用进行了复制。

int[][] arrayd1 = new int[][]{{1,2,3},{4,5,6}};
int[][] arrayd2 = arrayd1.clone();

执行结果如下:


基本数据类型二维数组的clone

arrayd1[0]和arrayd2[0]是同一个对象,所以说对于二维数组不能直接用clone进行深拷贝。


2.3 Arrays.copy()

Arrays.copy()可以实现对数组的拷贝,跟踪其源码,可以看到:

Arrays.copy()源码

最终调用的是System.arraycopy(),下面我们来使用Arrays.copy()进行拷贝。
基本数据类型:

int[] array1 = new int[]{1,2,3};
int[] array2 = Arrays.copyOf(array1, array1.length);
array2[1] = 3;

执行结果:


使用Arrays.copy()拷贝基本数据类型数组

可以看到和使用clone方法一致

引用数据类型:

Clone[] clones1 = new Clone[]{new Clone(),new Clone()};
Clone[] clones2 = Arrays.copyOf(clones1, clones1.length);

执行结果:


引用数据类型的Arrays.copy()

和使用clone方法一致。


总结

(1)一个对象要想使用Object类方法中clone(),那么必须要实现Cloneable接口,否则会抛出CloneNotSupportedException异常
(2)对象的clone,对于对象中基本数据类型成员变量是完全复制一份,对于引用类型成员变量是两个不同的指针指向同一个对象
(3)引用数据类型一维数组使用clone时不需要实现Cloneable接口
(4)基本数据类型一维数组的clone是完全的复制了一份,引用数据类型一维数组的clone生成了新的对象,但是两个对象同一个数组下标指向的对象是同一个
(5)基本数据类型二维数组的clone和引用数据类型一维数组的clone一致

有待思考

java中深拷贝如何实现?

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,026评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,655评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,726评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,204评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,558评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,731评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,944评论 2 314
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,698评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,438评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,633评论 2 247
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,125评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,444评论 3 255
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,137评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,103评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,888评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,772评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,669评论 2 271

推荐阅读更多精彩内容

  • 实际开发中可能会需要在一个对象的基础上拷贝一份相同的对象,与原始对象没有关联。这就需要了解下面的java浅拷贝和深...
    taidu阅读 191评论 0 0
  • 目录介绍 01.对象拷贝有哪些 02.理解浅拷贝2.1 什么是浅拷贝2.2 实现浅拷贝案例 03.理解深拷贝3.1...
    杨充211阅读 832评论 0 1
  • 一、基本数据类型 & 引用类型 1.1 基本概念 在讨论 浅拷贝 & 深拷贝 这个问题之前,我们需要先了解 基本数...
    泽毛阅读 4,847评论 2 17
  • Java的浅拷贝与深拷贝 一、概念 浅拷贝浅拷贝仅仅复制所考虑的对象(包括对象中的基本变量),而不复制它所引用的对...
    JackKuang阅读 374评论 0 0
  • Java深拷贝和浅拷贝 对象拷贝有哪些 对象拷贝(Object Copy)就是将一个对象的属性拷贝到另一个有着相同...
    程序员will阅读 334评论 0 0