大厂面试手撕源码之java数组拷贝

深拷贝与浅拷贝的关键之处在于是否分配了新的内存空间。

1.使用for循环进行数组拷贝(深拷贝)

	int[] array=new int[] {
    
    1,2,3,4};
	int[] array1=new int[array.length];
	for(int i=0;i<array.length;i++) {
    
    
		array1[i]=array[i];
	}	
	int[][] array2=new int[][] {
    
    {
    
    1,3,2},{
    
    1,4,5},{
    
    4,2,5}};
	int[][] array3=new int[array2.length][array2[0].length];
	for(int i1=0;i1<array2.length;i1++) {
    
    
		for(int j=0;j<array2[i1].length;j++) {
    
    
			array3[i1][j]=array2[i1][j];
		}
	}
	array3[0][0] = 11;    //测试(如果修改array3的值,显然不会修改array2的值)
	System.out.println(Arrays.deepToString(array2));
	System.out.println(Arrays.deepToString(array3));

其中Arrays.deepToString()用于打印二维数组。
Arrays.toString()打印一维数组。

2.使用Arrays.copyOf(),本质仍是调用System.arraycopy()(深拷贝

Arrays.copyOf()源码解读:

//非基本数据类型
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
    
    
        @SuppressWarnings("unchecked")
        //返回值类型,如果返回的数组类型和原始数组一致,否则,通过反射机制创建一个新的类型的数组实例。
        T[] copy = ((Object)newType == (Object)Object[].class)
            ? (T[]) new Object[newLength]
            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }
//基本数据类型
public static int[] copyOf(int[] original, int newLength) {
    
    //original为原数组
        int[] copy = new int[newLength];//分配新的堆内存空间
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));//调用System的arraycopy方法,其中参数:
//1:Object src:这个代表源数组
//2:int srcPos:这个代表复制时要从源数组的什么位置开始
//3:Object dest:这个是目标数组,就是我们要把数组复制到这个数组
//4:int destPos:这个代表你要把要复制的内容从到目标数组的什么位置开始
//5:int length:这个就是源数组要把多长的长度复制到目标数组
        return copy;
    }

那么为什么要调用Math.min函数来获取目标数组的长度呢?
源码解释如下:
*Copies the specified array, truncating or padding with nulls (if necessary)
* so the copy has the specified length. For all indices that are
* valid in both the original array and the copy, the two arrays will
* contain identical values. For any indices that are valid in the
* copy but not the original, the copy will contain null.
* Such indices will exist if and only if the specified length
* is greater than that of the original array.
* The resulting array is of the class newType.

即:如果目标数组的长度(即给定的newLength)小于原始数组的长度,则截取原始数组中目标数组长度的部分,反之,则取目标数组的长度,没有值的地方以null填充

3.直接调用System.arraycopy()函数(深拷贝

源码如下:

public static native void arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length);

解释见上!
关于native关键字的补充说明:使用native关键字说明这个方法是原生函数,也就是这个方法是用C/C++语言实现的,并且被编译成了DLL,由java去调用。 这些函数的实现体在DLL中,JDK的源代码中并不包含,你应该是看不到的。对于不同的平台它们也是不同的。这也是java的底层机制,实际上java就是在不同的平台上调用不同的native方法实现对操作系统的访问的。

4.使用Object的clone方法(深拷贝)

protected native Object clone() throws CloneNotSupportedException;

clone方法是从Object类继承过来的,基本数据类型(int ,boolean,char,byte,short,float ,double,long)都可以直接使用clone方法进行克隆,注意String类型是因为其值不可变所以才可以使用。其他引用数据类型需要实现Cloneable接口,通过实现clone()方法进行深拷贝。

参考链接:
【1】JAVA基础随笔-SYSTEM.ARRAYCOPY()方法使用心得
【2】Java中数组的几种拷贝方式

猜你喜欢

转载自blog.csdn.net/qq_44713855/article/details/108031659