copyOf(T[] original, int newLength)

拷贝数组,其内部调用了 System.arraycopy() 方法,从下标 0 开始,如果超过原数组长度,则会用 null 进行填充
Arrays.copyOf( 或 System.arraycopy)复制确实是浅拷贝,只复制了对象的引用(内存地址),并没有为每个元素新创建对象

源码

  1. public static <T> T[] copyOf(T[] original, int newLength) {
  2. return (T[]) copyOf(original, newLength, original.getClass());
  3. }
  4. public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
  5. @SuppressWarnings("unchecked")
  6. T[] copy = ((Object)newType == (Object)Object[].class)
  7. ? (T[]) new Object[newLength]
  8. : (T[]) Array.newInstance(newType.getComponentType(), newLength);
  9. System.arraycopy(original, 0, copy, 0,
  10. Math.min(original.length, newLength));
  11. return copy;
  12. }

特性

  • 基本数据类型:我们无法通过修改复制的基本数据类型来影响原数据,因为基本类型之间的赋值是创建新的拷贝,直接存储在JVM栈上的(局部变量),数据本身的值就是存储在栈空间里面。
  • String类型:String类是final类,无论是以字面量赋值(常量池),还是new方式赋值(堆),字符串都是一个不可变对象,所以无法通过某个字符串对象的引用地址改变真正的值
  • 对象引用类型:只有这时我们才能通过内存地址改变对象值,从而改变原数组具有相同内存地址的元素!

实践

  • int数组 ```java Integer[] i1 = new Integer[]{1,2,3}; Integer[] i2 = Arrays.copyOf(i1,5); System.out.println(i1); // [Ljava.lang.Integer;@b1bc7ed System.out.println(i2); // [Ljava.lang.Integer;@7cd84586 System.out.println(Arrays.toString(i2)); // [1, 2, 3, null, null]

i2[2]=Integer.valueOf(0); System.out.println(Arrays.toString(i1)); // [1, 2, 3] System.out.println(Arrays.toString(i2)); // [1, 2, 0, null, null] 复制后的i2数组的确不同于原数组i1(内存地址不同),并且修改复制数组的Integer元素,对原数组并无影响!

  1. - String数组
  2. ```java
  3. String[] s1 = new String[]{"1","2","3"};
  4. String[] s2 = Arrays.copyOf(s1,5);
  5. System.out.println(s1); // [Ljava.lang.String;@30dae81
  6. System.out.println(s2); // [Ljava.lang.String;@1b2c6ec2
  7. System.out.println(Arrays.toString(s2)); // [1, 2, 3, null, null]
  8. s2[2]="0";
  9. System.out.println(Arrays.toString(s1)); // [1, 2, 3]
  10. System.out.println(Arrays.toString(s2)); // [1, 2, 0, null, null]
  11. 复制的string数组元素改变依旧对原数组无影响
  • 对象数组 ```java class Student{ private String name; Student(String name){this.name=name;}

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

    @Override public String toString() {return “Student{name=” + name + ‘}’;} } Student[] students = new Student[]{new Student(“zhang1”),new Student(“zhang2”)}; Student[] copy = Arrays.copyOf(students,3); System.out.println(students);// [Lcom.example.demo.test.Student;@30dae81 System.out.println(copy); // [Lcom.example.demo.test.Student;@1b2c6ec2 System.out.println(Arrays.toString(copy)); // [Student{name=zhang1}, Student{name=zhang2}, null] 第一种 修改数组元素对象的一个属性 copy[1].setName(“zhang”); System.out.println(Arrays.toString(students)); // [Student{name=zhang1}, Student{name=zhang}] System.out.println(Arrays.toString(copy)); // [Student{name=zhang1}, Student{name=zhang}, null]

第二种 新换了一个对象的内存地址 copy[1] = new Student(“zhang”); System.out.println(Arrays.toString(students)); // [Student{name=zhang1}, Student{name=zhang2}] System.out.println(Arrays.toString(copy)); // [Student{name=zhang1}, Student{name=zhang}, null] 当数组元素为对象时,改变复制数组copy的元素属性确实会影响原数组,说明Arrays.copyOf只复制对象地址,并没有新创建数组元素 ```