java数组的深复制

guoyipeng 发布于:2016-4-24 23:10  有 1776 人浏览,获得评论 0 条  

本文地址:http://www.dutycode.com/post-122.html
除非注明,文章均为 www.dutycode.com 原创,欢迎转载!转载请注明本文地址,谢谢。

先说一下java对象深复制的概念:

被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。我们可以理解为更改复制对象中的引用的其他的对象的变量的值并不会更改原对象的的值,换句话讲,深复制指的是两个对象中引用的其他的对象指向的是java堆内存的两个不同位置。

那么,java数组是不是可以是实现深复制呢?

首先来看一下当数组是基本数据类型时,下面的代码中创建第一个int类型数组arr1,然后通过clone()方法创建数组arr2,之后对arr2进行更改。

public static void main(String[] args) {

int []arr1 = {1,2};

int []arr2 = arr1.clone();

System.out.println("arr2[0]:" + arr2[0] + ",arr2[1]:" + arr2[1]);

arr2[0] = 3; // 更改数组arr2中的第一个值

System.out.println("arr2[0]:" + arr2[0]);

System.out.println("arr1[0]:" + arr1[0]);

}

运行结果:

91M9VZ($UDH5[OC8{11%_]U.jpg

可以看到,更改数组arr2的值并没有影响数组arr1的值,通过调用对象的clone()就实现了基本类型数组的深复制。因为java中基本类型数据采用的是值传递,那么当数组类型是一个bean的时候,还可不可以实现深复制呢。

看下一个的例子,类Animal,包含两个变量age和sex,然后我们在test()方法中新建两个Animal对象a1和a2,然后新建一个名字为arr1的Animal数组,长度为2,值为a1和a2,之后通过clone()方法创建了数组arr2,之后更改arr2数组中第一个引用对象的age值,我们运行看下结果。

public class ArrayClone {

public static void main(String[] args) {

ArrayClone arrayClone = new ArrayClone();

arrayClone.test();

}

public void test(){

Animal a1 = new Animal(1, 1);

Animal a2 = new Animal(2, 2);

Animal[] arr1 = new Animal[]{a1,a2};

Animal[] arr2 = arr1.clone();

System.out.println("更改前arr1[0].age:" + arr1[0].age);

System.out.println("更改前arr2[0].age:" + arr2[0].age);

arr2[0].age = 3;

System.out.println("更改后arr1[0].age:" + arr1[0].age);

System.out.println("更改后arr2[0].age:" + arr2[0].age);


}

}

class Animal {

int age;

int sex;

Animal(int age, int sex){

this.age = age;

this.sex = sex;

}

}

运行结果:

D3796A0D-0F07-443C-B25C-838DC94A5BDD.png

通过结果可以看到,克隆后的对象更改值同时也影响了源对象,那么怎样才能实现java数组的深复制呢,我们试着做一下改动:

1. Animal类实现Cloneable接口。

2. Animal类增加clone()方法。

Animal类代码修改如下:

class Animal implements Cloneable {

int age;

int sex;

Animal(int age, int sex){

this.age = age;

this.sex = sex;

}

@Override

protected Animal clone() {

Animal a = null;

try {

a = (Animal)super.clone();

} catch (Exception e) {

e.printStackTrace();

}

return a;

}

}

其余代码不变,运行看下结果:

2E403400-6F7C-483E-85EE-D43728DE79B3.png

可以看出,结果还是没有改变。那么既然Animal类实现了Cloneable接口,又重写了clone()方法,我们就可以通过arr1中的引用对象clone给arr2,如下面的代码,创建数组arr2,数组长度为arr1的长度,然后通过遍历arr1中的元素clone赋值给arr2。

public void test(){

Animal a1 = new Animal(1, 1);

Animal a2 = new Animal(2, 2);

Animal[] arr1 = new Animal[]{a1,a2};

Animal[] arr2 = new Animal[arr1.length];

for (int i = 0; i < arr1.length; i++) {

arr2[i] = arr1[i].clone();

}

System.out.println("更改前arr1[0].age:" + arr1[0].age);

System.out.println("更改前arr2[0].age:" + arr2[0].age);

arr2[0].age = 3;

System.out.println("更改后arr1[0].age:" + arr1[0].age);

System.out.println("更改后arr2[0].age:" + arr2[0].age);

}

运行看下结果:

0114EE50-AE62-4DED-9CBA-2B2BE44E54CE.png

正如期待的那样,实现了java数组的深复制,克隆得到的对象更改值并不会影响到源对象。



版权所有:《攀爬蜗牛》 => 《java数组的深复制
本文地址:https://www.dutycode.com/post-122.html
除非注明,文章均为 《攀爬蜗牛》 原创,欢迎转载!转载请注明本文地址,谢谢。