System.arraycopy()和Arrays.copyof()

因为在看集合源码的时候经常会看到这两个方法,以前也没怎么接触过,导致傻傻分不清楚,这里正好记录下

1.System.arraycopy()

该方法是本地方法

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

src - 被复制的数组
srcPos - 源数组要被复制的起始位置
dest - 目标数组
destPos - 目标数组放置的起始位置
length - 数组复制的长度

举个例子
public class Student {

    private String name;
    private String sex;
    private String email;

    public Student(String name, String sex, String email) {
        this.name = name;
        this.sex = sex;
        this.email = email;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", email='" + email + '\'' +
                '}';
    }

    @Test
    public void arrayOfTest() {
        Student[] students = new Student[] {
                new Student("CCC","male","[email protected]"),
                new Student("BBB","female","[email protected]"),
                new Student("AAA","female","[email protected]"),
        };

        Student[] target = new Student[students.length];

        System.arraycopy(students,0, target,0,students.length);

        target[0].setName("LWH");

        System.out.println("修改目标对象属性值后的原对象:");
        for (Student stu: students){
            System.out.println(stu);
        }

    }
}

结果:

修改目标对象属性值后的原对象:
Student{name='LWH', sex='male', email='[email protected]'}
Student{name='BBB', sex='female', email='[email protected]'}
Student{name='AAA', sex='female', email='[email protected]'}

修改目标对象属性值后得对象:
Student{name='LWH', sex='male', email='[email protected]'}
Student{name='BBB', sex='female', email='[email protected]'}
Student{name='AAA', sex='female', email='[email protected]'}

改变前后 Student 中得属性值都发生了改变,可见 System.arraycopy 方法实现了浅拷贝,即对引用数据类型进行引用般的传递


2.Arrays.copyof()

public static <T> T[] copyOf(T[] original,
                             int newLength)

original:要被复制的数组
newLength:需要被复制的数组的长度

源码分析

因为 Arrays 里面有很多 copyof 的重载方法,其实本质都是一样的,底层都是调用 System.arraycopy 本地方法,然后返回复制后的数组。这里我就列举一个 int 类型的和一个泛型类的

// 传入 int 类型的数组
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;
}

// 传入泛型类的数组
public static <T> T[] copyOf(T[] original, int newLength) {
    return (T[]) copyOf(original, newLength, original.getClass());
}

public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
    // 判断传入的参数组参数是否是 Object 类的
    T[] copy = ((Object)newType == (Object)Object[].class)
        // 如果是,则直接初始化一个 Object 类的数组
        ? (T[]) new Object[newLength]
        // 如果不是,则直接转换为传入的参数类型后在对数组进行初始化
        : (T[]) Array.newInstance(newType.getComponentType(), newLength);
    System.arraycopy(original, 0, copy, 0,
                     Math.min(original.length, newLength));
    //返回复制后的数组
    return copy;
}


举个例子
@Test
public void copyofTest() {
    Student[] students = new Student[] {
            new Student("CCC","male","[email protected]"),
            new Student("BBB","female","[email protected]"),
            new Student("AAA","female","[email protected]"),
    };

    Student[] students1 = Arrays.copyOf(students, 3);

    students1[0].setName("LWH");

    System.out.println("修改目标对象属性值后的原对象:");
    for (Student stu: students1) {
        System.out.println(stu);
    }

    System.out.println("修改目标对象属性值后得对象:");
    for(Student stu: students) {
        System.out.println(stu);
    }
}

结果:

修改目标对象属性值后的原对象:
Student{name='LWH', sex='male', email='[email protected]'}
Student{name='BBB', sex='female', email='[email protected]'}
Student{name='AAA', sex='female', email='[email protected]'}

修改目标对象属性值后得对象:
Student{name='LWH', sex='male', email='[email protected]'}
Student{name='BBB', sex='female', email='[email protected]'}
Student{name='AAA', sex='female', email='[email protected]'}

结果和 System.arraycopy 方法一样,毕竟底层调用的就是 System.arrcopy 嘛,其实本质是一样的,也是浅拷贝


3.总结

System.arraycopy

  • 该方法需要自己定义一个目标数组,同时可以自己定制复制的内容,即从被复制数组的哪个位置开始,复制到目标数组的哪个位置,可以选择复制的长度
  • 适用于数组的元素的前后移动,如插入,删除等等
  • 该方法的复制是浅拷贝

Arrays.copyof

  • 方法可以看作是精简版的 System.arraycopy 数组,因为不需要自己定义目标数组,而且只能从被复制数组的头部复制目标数组的头部,可以选择复制的长度
  • 它主要是用来将原数组全部拷贝到一个新长度的数组,适用于数组扩容
  • 该方法的复制是浅拷贝

4.参考

https://segmentfault.com/a/1190000009922279
https://www.jianshu.com/p/840976f14950

猜你喜欢

转载自blog.csdn.net/babycan5/article/details/82588494