java.lang.System.arraycopy() 与java.util.Arrays.copyOf()的区别
一、java.lang.System.arraycopy()
该方法的声明:
/* @param src 源数组 * @param srcPos 源数组中的起始位置 * @param dest 目标数组 * @param destPos 目标数组中的起始位置 * @param length 需要被复制的元素个数 * @exception IndexOutOfBoundsException 如果在复制的过程中发生索引溢界异常 * @exception ArrayStoreException 如果源数组中的元素因为类型不匹配不能被复制到目标数组中 * @exception NullPointerException 如果源数组为null或者目标数组为null */ public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length); //由修饰符native可知,该方法调用的为JDK中的底层函数
该方法实现的功能为:从指定源数组中指定的位置开始,依次将元素复制到目标数组的指定位置,复制的元素个数为length参数。即,
将数组src[srcPos, ..., srcPos+length-1]中的元素复制到数组dest[destPos, ..., destPos+length-1]中。
如果源数组(src)和目标数组(dest)为相同的数组对象,则复制过程为:
① 将源数组中需复制的元素src[srcPos, ..., srcPos+length-1]复制到一个临时数组中,长度为length;
② 然后将临时数组中的内容复制到目标数组dest[destPos, ..., destPos+length-1]中。
二、java.util.Arrays.copyOf()
该方法的声明:
/* @param <T> 数组中元素的类型 * @param original 被复制数组 * @param newLength 返回的数组的长度 * @return 返回源数组的一个“副本”,为了去达到指定的长度,必要情况下需截断或用null值填充 * @throws NegativeArraySizeException 如果参数newLength为负值 * @throws NullPointerException 如果参数original为null * @since 1.6 */ @SuppressWarnings("unchecked") public static <T> T[] copyOf(T[] original, int newLength) { return (T[]) copyOf(original, newLength, original.getClass()); } /* @param <U> 源数组中元素的类型 * @param <T> 返回数组中元素的类型 * @param original 被复制数组 * @param newLength 返回的数组的长度 * @param newType 返回数组的类型 * @return 返回源数组的一个“副本”,为了去达到指定的长度,必要情况下需截断或用null值填充 * @throws NegativeArraySizeException 如果参数newLength为负值 * @throws NullPointerException 如果参数original为null * @throws ArrayStoreException 如果源数组中的元素不能被复制到类型为newType的数组中 * @since 1.6 */ 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] //(返回数组)的类型为Object[]时 : (T[]) Array.newInstance(newType.getComponentType(), newLength); //用newType的组件类型,长度newLength去创建一个新的数组 System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); //截断或用null值填充 return copy; } //java.util.Arrays重载了很多copyOf()方法 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; }
该方法实现的功能为:按指定的长度复制给定的源数组,必要情况下需截断或用null值填充。
Arrays.copyOf()的实现方式是:
① 内部新建一个长度为指定长度参数newLength的数组copy[];
② 调用System.arraycopy(original, 0, copy, 0,Math.min(original.length, newLength))完成对数组复制的功能
if(original.length >= newLength) 截断original[];original[0, ..., newLength-1] -> copy[0, ..., newLength-1]
if(original.length < newLength) 用null值填充;original[0, ..., original.length-1] -> copy[0, ..., original.length-1]
nulls -> copy[original.length, ..., newLength-original.length+1]
③ 返回一个长度为newLength的数组copy[],元素为②中得到的对应值
三、异同
1) Arrays.copyOf()内部是通过System.arraycopy()实现的。
2) System.arraycopy()通过对srcPos,destPos的设置完成对数组的任意部分复制功能;而Arrays.copyOf()只能从下标为0的元素开始复制。
3)System.arraycopy()中会因为srcPos+length > src.length 或 destPos+length > dest.length而报ArrayIndexOutOfBoundsException;而Arrays.copyOf()中不会因此而报错,因为Arrays.copyOf()返回的为方法内部新建的一个指定长度的数组。
String[] a = {"a","b","c","d","e"}; String[] b = new String[4]; //System.arraycopy(a, 0, b, 0, 5); //java.lang.ArrayIndexOutOfBoundsException //b = Arrays.copyOf(a, 4); //截断a[],b={"a","b","c","d"} b = Arrays.copyOf(a, 5); //b={"a","b","c","d","e"} //b = Arrays.copyOf(a, 6); //null值填充,b={"a","b","c","d","e",null}
4) 在System.arraycopy()方法中,如果目标数组dest==null,则会报NullPointerException;而Arrays.copyOf()中不会因此而报错。
String[] a = {"a","b","c","d","e"}; String[] b = null; //System.arraycopy(a, 0, b, 0, 5); //java.lang.NullPointerException b = Arrays.copyOf(a, 5); //b={"a","b","c","d","e"}
5)System.arraycopy()方法中目标数组作为参数;而Arrays.copyOf()中目标数组作为返回值。
6) System.arraycopy()方法和Arrays.copyOf()方法均可以实现数组类型的向上转换,即子类型的数组可以复制到父类型数组中;但不可以实现向下转换,即父类型的数组不可以复制到子类型数组中。
class A {} class B extends A{} A a1 = new A(); A[] parent = {a1,a1,a1,a1,a1}; B[] child = new B[5]; //child = (B[]) Arrays.copyOf(parent, 5); //java.lang.ClassCastException //System.arraycopy(parent, 0, child, 0, 5); //java.lang.ArrayStoreException B b1 = new B(); B[] child = {b1,b1,b1,b1,b1}; A[] parent = new A[5]; //parent = Arrays.copyOf(child,5); //复制成功 //System.arraycopy(child, 0, parent, 0, 5); //复制成功