System.arraycopy()方法及对象的深复制和浅复制

1、System.arraycopy方法实现数组的复制

1-1:System中提供了一个native静态方法arraycopy(),可以使用这个方法实现数组之间的复制。对于普通的一维数组来说,会复制每个数组的值到另一个数组中,即每个元素都是按值传递,修改副本不会影响原来的值。方法原型及复制复制基本类型数组的示例如下:

/**
 * System.arraycopy的方法原型
 * @param src       要复制的源数组
 * @param srcPos    源数组要复制的起始位置(从0开始)
 * @param dest      要复制的目标数组
 * @param destPos   目标数组的起始位置(从0开始)
 * @param length    要复制的长度
*/
public static native void arraycopy(Object src,  int  srcPos,
            Object dest, int destPos, int length);
public static void main(String[] args) {
    int[] nums = {1024, 1025, 1026, 1027, 1028};
    int[] copyOfNums = new int[nums.length];
    System.arraycopy(nums, 0, copyOfNums, 0, nums.length);
    //修改拷贝数组的元素
    copyOfNums[3] = 1234;
    //观察原数组有无变化
    System.out.println(Arrays.toString(nums));
}

输出结果: [1024, 1025, 1026, 1027, 1028]
因为复制普通数组时,按值传递,会把每个元素的值复制一份给新数组,所以修改副本不会影响原来的值。

System.arraycopy()方法及对象的深复制和浅复制_第1张图片
字符串数组就比较特殊了,先看代码:

String[] names = {"王昭君", "赵飞燕", "陈圆圆", "杨玉环", "苏妲己"};
System.out.println("原数组中每个元素的哈希码:");
for(String name : names) {
    System.out.print(Integer.toHexString(name.hashCode()) + ", ");
}
String[] copyOfNames = new String[names.length];
System.arraycopy(names, 0, copyOfNames, 0, names.length);
copyOfNames[1] = "洛神甄氏";
System.out.println("\n复制数组中每个元素的哈希码,1号元素的哈希码已经发生了改变:");
for(String name : copyOfNames) {
    System.out.print(Integer.toHexString(name.hashCode()) + ", ");
}
System.out.println();
//修改copyOfNames中元素后的原数组内容没有改变
System.out.println(Arrays.toString(names));

运行后的结果如下:
原数组中每个元素的哈希码:
1be7059, 225f8ec, 23f0508, 1929eae, 1f6458e,
复制数组中每个元素的哈希码,1号元素的哈希码已经发生了改变:
1be7059, 336eea6e, 23f0508, 1929eae, 1f6458e,
[王昭君, 赵飞燕, 陈圆圆, 杨玉环, 苏妲己]
内存图如下:

System.arraycopy()方法及对象的深复制和浅复制_第2张图片
1-2:复制对象数组

//实体类
public class Beauty {
    private String name;
    private int level;
    private double face;

    public Beauty() {}

    public Beauty(String name, int level, double face) {
        this.setName(name);
        this.setLevel(level);
        this.setFace(face);
    }

    @Override
    public String toString() {
        return name + ", " + level + ", " + face;
    }
    //省略 getters/setters
}
//测试方法
public class ArraycopyDemo {
    public static void main(String[] args) {
        Beauty[] beauties = new Beauty[5];
        beauties[0] = new Beauty("王昭君", 5, 86.25);
        beauties[1] = new Beauty("赵飞燕", 6, 76.25);
        beauties[2] = new Beauty("陈圆圆", 7, 56.25);
        beauties[3] = new Beauty("杨玉环", 8, 66.25);
        beauties[4] = new Beauty("苏妲己", 9, 96.25);
        Beauty[] newBeauties = new Beauty[beauties.length];
        System.arraycopy(beauties, 0, newBeauties, 0, beauties.length);
        //修改复制后数组元素的属性
        newBeauties[1].setName("洛神甄氏");

        //打印原数组中的内容,观察1号元素的name属性,已经被修改了
        for(Beauty beauty : beauties) {
            System.out.println(beauty);
        }       
    }
}

运行结果:
System.arraycopy()方法及对象的深复制和浅复制_第3张图片
内存原理如下:

System.arraycopy()方法及对象的深复制和浅复制_第4张图片
得出的结论:
1、当数组为一维数组,且元素为基本类型或String类型时,属于深复制,即原数组与新数组的元素不会相互影响
2、当数组为多维数组,或一维数组中的元素为引用类型时,属于浅复制,原数组与新数组的元素引用指向同一个对象
这里说的影响,是两个数组复制后对应的元素,并不一定是下标对应
String的特殊是因为它的不可变性
多维数组实际上可以理解为一维数组中的每个元素又是一个一维或多维数组的首地址,所以复制时的效果与对象数组的结果是一样的

安装遇到问题,可加老九君个人QQ:614940318,请备注来自CSDN
老九学堂免费C、C++、Java课程地址: https://study.163.com/courses-search?keyword=老九学堂

你可能感兴趣的:(Java相关)