首页   >   代码编程

Arrays.copyOf和System.arraycopy的关系和区别

实现一个复制数组的功能,java为我们提供了两种API,Arrays.copyOf和System.arraycopy,那么这二者有什么区别呢?又有着什么样的联系呢?

老规矩,我们直接看源码:

/**
 * 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 <tt>null</tt>.
 * Such indices will exist if and only if the specified length
 * is greater than that of the original array.
 * The resulting array is of exactly the same class as the original array.
 *
 * @param <T> the class of the objects in the array
 * @param original the array to be copied
 * @param newLength the length of the copy to be returned
 * @return a copy of the original array, truncated or padded with nulls
 *     to obtain the specified length
 * @throws NegativeArraySizeException if <tt>newLength</tt> is negative
 * @throws NullPointerException if <tt>original</tt> is null
 * @since 1.6
 */
@SuppressWarnings("unchecked")
public static <T> T[] copyOf(T[] original, int newLength) {
    return (T[]) copyOf(original, newLength, original.getClass());
}

这是我们进入到Arrays.copyOf方法看到的代码,由于支持了泛型,所以又重载了一个copyOf方法,第三个参数是第一个参数的class,也就是需要复制的数组类型

/**
 * 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 <tt>null</tt>.
 * 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 <tt>newType</tt>.
 *
 * @param <U> the class of the objects in the original array
 * @param <T> the class of the objects in the returned array
 * @param original the array to be copied
 * @param newLength the length of the copy to be returned
 * @param newType the class of the copy to be returned
 * @return a copy of the original array, truncated or padded with nulls
 *     to obtain the specified length
 * @throws NegativeArraySizeException if <tt>newLength</tt> is negative
 * @throws NullPointerException if <tt>original</tt> is null
 * @throws ArrayStoreException if an element copied from
 *     <tt>original</tt> is not of a runtime type that can be stored in
 *     an array of class <tt>newType</tt>
 * @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]
        : (T[]) Array.newInstance(newType.getComponentType(), newLength);
    System.arraycopy(original, 0, copy, 0,
                     Math.min(original.length, newLength));
    return copy;
}

大家看到了什么?

对,没错,其实copyOf的底层也是调用了System.arraycopy方法来实现的。

再去看System.arraycopy的源码:

/**
 * Copies an array from the specified source array, beginning at the
 * specified position, to the specified position of the destination array.
 * A subsequence of array components are copied from the source
 * array referenced by <code>src</code> to the destination array
 * referenced by <code>dest</code>. The number of components copied is
 * equal to the <code>length</code> argument. The components at
 * positions <code>srcPos</code> through
 * <code>srcPos+length-1</code> in the source array are copied into
 * positions <code>destPos</code> through
 * <code>destPos+length-1</code>, respectively, of the destination
 * array.
 * <p>
 * If the <code>src</code> and <code>dest</code> arguments refer to the
 * same array object, then the copying is performed as if the
 * components at positions <code>srcPos</code> through
 * <code>srcPos+length-1</code> were first copied to a temporary
 * array with <code>length</code> components and then the contents of
 * the temporary array were copied into positions
 * <code>destPos</code> through <code>destPos+length-1</code> of the
 * destination array.
 * <p>
 * If <code>dest</code> is <code>null</code>, then a
 * <code>NullPointerException</code> is thrown.
 * <p>
 * If <code>src</code> is <code>null</code>, then a
 * <code>NullPointerException</code> is thrown and the destination
 * array is not modified.
 * <p>
 * Otherwise, if any of the following is true, an
 * <code>ArrayStoreException</code> is thrown and the destination is
 * not modified:
 * <ul>
 * <li>The <code>src</code> argument refers to an object that is not an
 *     array.
 * <li>The <code>dest</code> argument refers to an object that is not an
 *     array.
 * <li>The <code>src</code> argument and <code>dest</code> argument refer
 *     to arrays whose component types are different primitive types.
 * <li>The <code>src</code> argument refers to an array with a primitive
 *    component type and the <code>dest</code> argument refers to an array
 *     with a reference component type.
 * <li>The <code>src</code> argument refers to an array with a reference
 *    component type and the <code>dest</code> argument refers to an array
 *     with a primitive component type.
 * </ul>
 * <p>
 * Otherwise, if any of the following is true, an
 * <code>IndexOutOfBoundsException</code> is
 * thrown and the destination is not modified:
 * <ul>
 * <li>The <code>srcPos</code> argument is negative.
 * <li>The <code>destPos</code> argument is negative.
 * <li>The <code>length</code> argument is negative.
 * <li><code>srcPos+length</code> is greater than
 *     <code>src.length</code>, the length of the source array.
 * <li><code>destPos+length</code> is greater than
 *     <code>dest.length</code>, the length of the destination array.
 * </ul>
 * <p>
 * Otherwise, if any actual component of the source array from
 * position <code>srcPos</code> through
 * <code>srcPos+length-1</code> cannot be converted to the component
 * type of the destination array by assignment conversion, an
 * <code>ArrayStoreException</code> is thrown. In this case, let
 * <b><i>k</i></b> be the smallest nonnegative integer less than
 * length such that <code>src[srcPos+</code><i>k</i><code>]</code>
 * cannot be converted to the component type of the destination
 * array; when the exception is thrown, source array components from
 * positions <code>srcPos</code> through
 * <code>srcPos+</code><i>k</i><code>-1</code>
 * will already have been copied to destination array positions
 * <code>destPos</code> through
 * <code>destPos+</code><i>k</I><code>-1</code> and no other
 * positions of the destination array will have been modified.
 * (Because of the restrictions already itemized, this
 * paragraph effectively applies only to the situation where both
 * arrays have component types that are reference types.)
 *
 * @param      src      the source array.
 * @param      srcPos   starting position in the source array.
 * @param      dest     the destination array.
 * @param      destPos  starting position in the destination data.
 * @param      length   the number of array elements to be copied.
 * @exception  IndexOutOfBoundsException  if copying would cause
 *               access of data outside array bounds.
 * @exception  ArrayStoreException  if an element in the <code>src</code>
 *               array could not be stored into the <code>dest</code> array
 *               because of a type mismatch.
 * @exception  NullPointerException if either <code>src</code> or
 *               <code>dest</code> is <code>null</code>.
 */
public static native void arraycopy(Object src,  int  srcPos,
                                    Object dest, int destPos,
                                    int length);

哇,这注释写的是真的多,不过我们看到方法用了native来修饰,说明这是一个java本地方法,我们没法再继续往下看了,但是有一点,那就是它必须传递一个相同类型的object数组

现在来总结一下二者的区别:

1、Arrays.copyOf是java.util包下面的集合辅助类,System.arraycopy是java.lang下面的本地方法;

2、System.arraycopy复制数组时,目标数组必须先被创建,Arrays.copyOf则不用自己创建目标数组;

一句话概括:

Arrays.copyOf是System.arraycopy的封装实现

Arrays.copyOf和System.arraycopy的关系和区别

特意写错了一个地方,给大家提个醒,在执行这些复制操作的时候,一定要注意下标的位置,否则一不小心就会出错!!!

QQ群Ⅰ: 686430774 (已满)

QQ群Ⅱ: 718410762 (已满)

QQ群Ⅲ: 638620451 (已满)

QQ群Ⅳ: 474195684

如果文章有帮到你,可以考虑请博主喝杯咖啡!

分享到:

欢迎分享本文,转载请注明出处!

作者:不忘初心

发布时间:2019-03-17

永久地址:https://www.jiweichengzhu.com/article/9daf9f4b616f4c48b9f43dd14693f9c8

评论