弄清Java深浅拷贝问题(一) ! 相关【System.arraycopy()方法、Arrays.copyOf()和Arrays.copyOfRan等】

 

下面是自己的总结:

基本概念

* 浅拷贝: 拷贝的是字面量,即数值,即引用(没有创建新的对象,只是将两个引用指向同一对象)

* 深拷贝: 拷贝的是对象! 这个过程中是要新建对象的,想一想对象的复杂程度和完全不可预测的各种可能结构,java api 怎么知道如何将对象拷贝呢,还不是得你自己动手

(emm 关于Object.clone()方法和Cloneable接口 java api 中默认的还是浅拷贝,不过可以自己在类中重写覆盖Object.clone()方法,从而实现深拷贝。详见另一篇博客:弄清Java深浅拷贝问题(二) !Object.clone()方法和Cloneable接口)

 

javadoc  对于Array.copyOf(T[] original, int newLength) 的描述

For all indices that are valid in both the original array and the copy, the two arrays will contain identical values.

注意看,描述中说的是“indentical values” ,就是将数组中保存的数值复制粘贴而已。

(1)数组元素是基本数据:因为数组中保存的值就是基本数据本身,所以Array.copyOf相当于新建了一个新的备份,所以可以看作“深拷贝”;

(2)对于数组元素是对象:因为数组中保存的并不是对象本身,而是对象的引用,对象本身是保存在堆上的。所以Array.copyOf只是将引用的值进行复制粘贴,过程中并没有创建新的对象,只是将对应的引用指向相同的对象

 

示例

(1)数组元素是基本数据(primitive)

        (a)浅拷贝:使用“=”

public class ShallowCopy {
	public static void main(String[] args) {
		int[] a = {1, 2};
		int[] b = a;
		b[1] = 7;
		System.out.println("a[1] = " + a[1]);
	}
}

                  控制台输出: a[1] = 7

         (b)深拷贝:for/while 循环一个一个复制;使用Array.copyOf等java api提供的方法

1. 示例1:
使用System.arraycopy

public class CopyArrayByarraycopy {
	public static void main(String[] args) {
		int[] a = {1, 2, 3, 4};
		int[] b = new int[4];
		
		System.arraycopy(a, 0, b, 0, a.length);
		b[3] = 7;
		
		System.out.println("Array a:");
		for (int i : a)
			System.out.print(i + " ");
		System.out.println();
		System.out.println("Array b:");
		for (int j : b)
			System.out.print(j + " ");
	}
}

输出:
Array a:
1 2 3 4
Array b:
1 2 3 7


2. 示例2:
使用Arrays.copyOf

//导入Arrays类
import java.util.Arrays;
 
public class CopyArrayByCopyof
{
       public static void main(String[] args)
     {
         int[] a = new int[10];
        
        //copyOf方法
        int[] copy = Arrays.copyOf(a, a.length * 2);
      //第一个参数为要拷贝的数组名,第二个为拷贝数组的大小(不限定大小,可用于扩大数组,如可以是a.length * 2)
 
       System.out.println(a[1] + " " +  copy[2] );
     }
}

输出:
0 0


3. 示例3
使用Object.clone

public class CopyArrayByClone {
	public static void main(String[] args) {
		int[] a = {1, 2, 3, 4};
		int[] b = a.clone();
		a[0] = 91;
		b[1] = 7;
		System.out.println("Array a:");
		for (int i : a)
			System.out.print(i + " ");
		System.out.println();
		System.out.println("Array b:");
		for (int j : b)
			System.out.print(j + " ");
	}
}

输出:
Array a:
91 2 3 4
Array b:
1 7 3 4

 

        copyOf 和  arraycopy 两者关系如下,可以看到copyOf调用arraycopy:

public static int[] copyOf(int[] original, int newLength) { 
   int[] copy = new int[newLength]; 
   System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); 
   return copy; 
}

 (2)浅拷贝:数组元素是对象(object)

         代码中使用System.arraycopy()  (另外几个方法效果都是一样的,都是浅拷贝)

public class Test {

    public static void main(String[] args) {
        NameValue[] instance1 = {
                new NameValue("name1", 1),
                new NameValue("name2", 2),
                new NameValue("name3", 3),
        };
        NameValue[] instance2 = new NameValue[instance1.length];

        // Print initial state
        System.out.println("Arrays before shallow copy:");
        System.out.println("Instance 1: " + Arrays.toString(instance1));
        System.out.println("Instance 2: " + Arrays.toString(instance2));

        // Perform shallow copy
        System.arraycopy(instance1, 0, instance2, 0, 3);

        // Change instance 1
        for (int i = 0; i < 3; i++) {
            instance1[i].change();
        }

        // Print final state
        System.out.println("Arrays after shallow copy:");
        System.out.println("Instance 1: " + Arrays.toString(instance1));
        System.out.println("Instance 2: " + Arrays.toString(instance2));
    }

    private static class NameValue {
        private String name;
        private int value;

        public NameValue(String name, int value) {
            super();
            this.name = name;
            this.value = value;
        }

        public void change() {
            this.name = this.name + "-bis";
            this.value = this.value + 1;
        }

        @Override
        public String toString() {
            return this.name + ": " + this.value;
        }
    }
}

运行结果显示,只是引用被拷贝了,所以对instance1对象数组的修改会影响instance2对象数组:

Arrays before shallow copy:
Instance 1: [name1: 1, name2: 2, name3: 3]
Instance 2: [null, null, null]
Arrays after shallow copy:
Instance 1: [name1-bis: 2, name2-bis: 3, name3-bis: 4]
Instance 2: [name1-bis: 2, name2-bis: 3, name3-bis: 4]

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Arrays.copyOf() 和 System.arraycopy() 都是用于数组的复制操作,但它们有一些不同之处。 Arrays.copyOf() 方法是在 Java 1.6 版本中引入的,它用于创建一个新的数组,并将源数组中的元素复制到新数组中。该方法具有以下两种重载形式: 1. copyOf(original, newLength):将原始数组的前 newLength 个元素复制到新数组中。如果新长度小于原始数组的长度,则新数组将被截断;如果新长度大于原始数组的长度,则新数组将被填充默认值。 2. copyOf(original, newLength, newType):与上述方法相似,但可以指定新数组的类型。 示例使用 Arrays.copyOf() 方法: ```java int[] original = {1, 2, 3, 4, 5}; int[] copy1 = Arrays.copyOf(original, 3); // 复制原数组的前三个元素 int[] copy2 = Arrays.copyOf(original, 7); // 复制原数组的所有元素,并用默认值填充额外位置 ``` System.arraycopy() 方法是在 Java 1.0 版本中引入的,它也用于将源数组中的元素复制到目标数组中。该方法的语法如下: ```java System.arraycopy(src, srcPos, dest, destPos, length); ``` 其中,src 是源数组,srcPos 是源数组中要开始复制的起始位置,dest 是目标数组,destPos 是目标数组中要开始粘贴的起始位置,length 是要复制的元素个数。 示例使用 System.arraycopy() 方法: ```java int[] src = {1, 2, 3, 4, 5}; int[] dest = new int[5]; System.arraycopy(src, 0, dest, 0, 5); // 复制 src 数组的所有元素到 dest 数组中 ``` 总结来说,Arrays.copyOf() 方法提供了更简洁的方式来复制数组,并且可以轻松地截取或填充数组。而 System.arraycopy() 方法则提供了更灵活的复制方式,可以指定复制的起始位置和复制的元素数量。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值