Java.util下Arrays.copyOf方法源码详解

Java.util下Arrays.copyOf方法源码详解

1. 测试最常用的两个参数的copeOf方法

    @Test
    public void TestArraysCopyOf(){
        String[] s1 = {"damon1","damon2","damon3"};
        String[] s2 = Arrays.copyOf(s1, 3);
        System.out.println(Arrays.toString(s2));
        String[] s3 = Arrays.copyOf(s1, 1);
        System.out.println(Arrays.toString(s3));
    }
/**
 * 输出结果如下
 * [damon1, damon2, damon3]
 * [damon1]
 */

2. Arrays.copyOf()源码部分

  1. 直接调用的方法
@SuppressWarnings("unchecked")
public static <T> T[] copyOf(T[] original, int newLength) {
    return (T[]) copyOf(original, newLength, original.getClass());
}

​ 这个方法就是取出传入数组的class对象作为第三个参数调用适用性更广的另一个函数而已.

  1. 间接调用的方法
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;
}

​ 注意点:

  1. 首先这个方法有两个泛型,一个是T,一个是U,T代表传入的第三个个参数newType(传入的类型的class对象),T代表传入的第一个对象original(即原数组的数据类型)

  2. 三元运算符的判断条件**((Object)newType == (Object)Object[].class)是用来判断newType是否是Object类型,在上述第一个方法的前提下代表判断原数组是否为Object类型的数组.(Object)newType**这里为什么要转型是因为不转型会报错.

    //System.out.println(ArrayList.class==Object[].class);
    //Operator '==' cannot be applied to 'java.lang.Class<java.util.ArrayList>', 'java.lang.Class<java.lang.Object[]>'
    System.out.println((Object)ArrayList.class==Object[].class);
    //这里用的已知的ArrayList的class对象,所以编译时直接可以判断为false,IDEA会有如下提示Condition '(Object)ArrayList.class==Object[].class' is always 'false' 
    
  3. 如果判断为真,即原数组是Object类型数组,则直接创建一个给定长度newLength的新的Object数组即可.(为什么要创建新数组呢?因为这个函数目的就是复制一个数组的指定部分到一个新数组.)

    如果判断为假,即原数组不是Object类型数组,则调用**(T[]) Array.newInstance(newType.getComponentType(), newLength)**这个方法是新建一个数组,数组类型为newType中元素的类型(默认返回Object类型,可强制转换为正确类型,详情看下列代码示例),长度为指定的newLength.


    public native Class<?> getComponentType();
    

    本地方法,返回数组内的元素类型,不是数组时,返回null

    public class SystemArrayCopy {
    
        public static void main(String[] args) {
            String[] o = {"aa", "bb", "cc"};
            System.out.println(o.getClass().getComponentType());
            System.out.println(Object.class.getComponentType());
        }
    }
    /*
    class java.lang.String
    null
    */
    

     private static native Object newArray(Class<?> componentType, int length)
            throws NegativeArraySizeException;
    

    创建一个类型与newType一样,长度为newLength的数组

    public static Object newInstance(Class<?> componentType, int length)
        throws NegativeArraySizeException {
        return newArray(componentType, length);
    }
    private static native Object newArray(Class<?> componentType, int length)
            throws NegativeArraySizeException;
    

    newInstance返回为Object,实质为数组

    public class SystemArrayCopy {
    
        public static void main(String[] args) {
            Object o = Array.newInstance(String.class, 10);
            System.out.println(o.getClass());
            System.out.println(String.class); // 用于对比
        }
    }
    /*
    class [Ljava.lang.String;
    class java.lang.String
    */
    

    可以看到,Array.newInstance的返回虽然是Object类型,但是它实质上是String数组,可以强制转换成String[],如:String[] arr = (String[]) Array.newInstance(String.class, 10);

  4. 创建好要返回的数组的类型和长度之后,就是调用**System.arraycopy(original, 0, copy, 0,Math.min(original.length, newLength));**这里是调用系统的方法来复制数组的内容,参数分别表示,原数组,原数组起始索引,目标数组,目标数组起始索引,复制的长度.

    复制的长度取original.length和newLength的最小值,这里就有可能指定的新长度小于原数组的长度,存在的截断的可能.

    @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.
    public static native void arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length);
    
  5. 复制完成后,返回对应的目标数组copy即可.

总结

在分析ArrayList源码的时候看到的,之前也在各种地方看到,一直没研究,这次借着其他的几篇资料做一个自己的总结.总之就是,越看源码越透彻的感觉.推荐这篇csdn,就是受到这位大佬的研究精神才写的.

Arrays.copyOf()方法详解-jdk1.8

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页