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中深拷贝如何实现?

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

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

友情链接更多精彩内容