欢迎纠错,转载注明出处,have a nice day!
今天在做项目的时候有个需求要用到二维数组复制,我不假思索地以为和一维数组一样,结果出错了,特此记录一下。
Arrays.copyOf()方法返回的拷贝数组的地址是否指向原数组?
答案很明显是否的,因为在源码中很明显是new了个新数组返回。
public static int[] copyOf(int[] original, int newLength) {
//new一个新数组,然后调用System.arraycopy复制
int[] copy = new int[newLength];
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
虽然返回的数组地址与原数组不同,但是数组中的数据就未必了,上代码:
新建两个数组,分别存放基本数据和对象,然后对他们进行拷贝,再对拷贝的数组的第一个元素进行修改。可以看出,啊a1数组的元素并未发生改变,而a2数组的元素改变了。
public class TestArraysCopy {
public static void main(String[] args) {
int[] a1 = new int[] {1, 2, 3, 4};
Num[] a2 = new Num[] {new Num(1), new Num(2), new Num(3), new Num(4)};
int[] c1 = Arrays.copyOf(a1, a1.length);
Num[] c2 = Arrays.copyOf(a2, a2.length);
c1[0] = 0;
c2[0].num = 0;
System.out.println("a1: " + a1[0] + " c1: " + c1[0]);//a1: 1 c1: 0
System.out.println("a2: " + a2[0].num + " c2: " + c2[0].num);//a2: 0 c2: 0
}
}
class Num{
int num;
public Num(int num) {
this.num = num;
}
}
可以看出,对于对象数组的copy,数组中的元素引用的是原数组中对象的地址。我们debug来看一下数组地址
发现,a1,a2与c1,c2的数组地址不同,但a2与c2的元素的地址是相同的,所以证实上面的说法。
那么二维数组的拷贝有什么不同吗?
我之前对二维数组的拷贝操作是这样的
int[][] a3 = new int[][] {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
int[][] c3 = Arrays.copyOf(a3, a3.length);
c3[0][0] = 0;
System.out.println("a3: " + a3[0][0] + " c3: " + c3[0][0]);//a3: 0 c3: 0
我们都知道,数组在java中是看做对象来处理的,如果按照我之前的操作,则会把a3中的每个子数组的地址传递到c3中。所以对二维数组的拷贝要这么做:
int[][] a3 = new int[][] {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
int[][] c3 = new int[a3.length][];
for (int i = 0; i < a3.length; i++) {
c3[i] = Arrays.copyOf(a3[i], a3[i].length);
}
c3[0][0] = 0;
System.out.println("a3: " + a3[0][0] + " c3: " + c3[0][0]);//a3: 1 c3: 0
先为c3开辟3个新地址,然后就和一维数组拷贝一样了。
注意:当二维数组是对象数组的时候,想要拷贝就只能老老实实用for循环,new一个新对象,将旧对象的数据传递给新对象。