欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2023-04-03 16:55:30
深拷贝与浅拷贝的关键之处在于是否分配了新的内存空间。1.使用for循环进行数组拷贝(深拷贝)int[] array=new int[] {1,2,3,4};int[] array1=new int[array.length];for(int i=0;i

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

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中数组的几种拷贝方式

本文地址:https://blog.csdn.net/qq_44713855/article/details/108031659