zoukankan      html  css  js  c++  java
  • Java复制数组的方法

      java数组拷贝主要有四种方法,分别是循环赋值,System.arraycopy(),Arrays.copyOf()(或者Arrays.copyOfRange)和clone()方法。下面分别介绍一下这几种拷贝。

    一、循环拷贝(速度相对比较慢)

      循环拷贝其实没什么好说的啦,就是用一个for循环进行元素的逐个拷贝,进行深拷贝或者浅复制这个大家可以自己把握。

    二、System.arraycopy(浅拷贝)

      这个是系统提供的拷贝方式,也是我们推荐使用的拷贝方式,它是浅拷贝,也就是说对于非基本类型而言,它拷贝的是对象的引用,而不是去新建一个新的对象。通过它的代码我们可以看到,这个方法不是用java语言写的,而是底层用c或者c++实现的,因而速度会比较快。

    1 public static native void arraycopy
    2 (Object src, int srcPos,Object dest, int destPos,int length);

      通过源代码我们可以看到,关键字native说明它不是用java语言写的,而是调用其他语言的代码。

    1、先来看看基本数据类型的System.arraycopy() 方法拷贝:

     1 import java.util.Arrays;
     2 public class TestDemo {
     3     public static void main(String[] args) {
     4  
     5         int[] array1 = new int[]{1,2,8,7,6};
     6         int[] array2 = new int[array1.length];
     7         System.arraycopy(array1, 0, array2, 0, array1.length);
     8  
     9         System.out.println("array1 = " + Arrays.toString(array1));
    10         System.out.println("array2 = " + Arrays.toString(array2));
    11         System.out.println("=========================");
    12  
    13         array2[0] = 100;
    14         System.out.println("array1 = " + Arrays.toString(array1));
    15         System.out.println("array2 = " + Arrays.toString(array2));
    16  
    17     }
    18 }

      这段程序的结果是:

    array1 = [1, 2, 8, 7, 6]
    array2 = [1, 2, 8, 7, 6]
    =========================
    array1 = [1, 2, 8, 7, 6]
    array2 = [100, 2, 8, 7, 6]

      由结果可以看出,当对复制数组的某个元素进行改变时,并不影响被复制数组对应元素,即对于基本数据类型来说System.arraycopy() 方法是深拷贝。 

    2、同样的,看一下当对象不是基本数据类型,而是引用数据类型时的情况

      看以下例子:

     1 class TestArray{
     2     private int val = 10;
     3     public void setVal(int val){
     4         this.val = val;
     5     }
     6     public int getVal(){
     7         return this.val;
     8     }
     9 }
    10  
    11 public class TestDemo {
    12     /**数组输出方法 */
    13     public static void printArray(TestArray[] array){
    14         for(int i = 0;i < array.length;i++){
    15             System.out.print(array[i].getVal()+" ");
    16         }
    17         System.out.println();
    18     }
    19  
    20     public static void main(String[] args) {
    21         TestArray[] array1 = new TestArray[3];
    22         // 数组引用赋值
    23         for (int i = 0; i < array1.length; i++){
    24             array1[i] = new TestArray();
    25         }
    26  
    27         TestArray[] array2 = new TestArray[array1.length];
    28         // 数组System.arraycopy()方法复制
    29         System.arraycopy(array1,0,array2,0,array1.length);
    30  
    31         printArray(array1);
    32         printArray(array2);
    33         System.out.println("==========");
    34  
    35         array2[0].setVal(100);;
    36         printArray(array1);
    37         printArray(array2);
    38     }
    39 }

      这段程序的结果是:

    10 10 10 
    10 10 10 
    ==========
    100 10 10 
    100 10 10

      由结果可以看出,当对复制数组的某个元素进行改变时,被复制数组对应元素也随之改变,即对于引用数据类型来说 System.arraycopy() 方法是浅拷贝。

    三、Arrays.copyOf(浅拷贝)

      这个方法也是浅拷贝,为什么呢?我们看一下它的源代码就知道了。

    1 public static byte[] copyOfRange(byte[] original, int from, int to) {
    2     int newLength = to - from;
    3     if (newLength < 0)
    4         throw new IllegalArgumentException(from + " > " + to);
    5     byte[] copy = new byte[newLength];
    6     System.arraycopy(original, from, copy, 0,Math.min(original.length - from, newLength));
    7     return copy;
    8 }

      可以看到其实Arrays.copyOf()方法在底层是调用了 System.arraycopy() 方法来实现复制,即可以把Arrays.copyOf() 方法看作是 System.arraycopy() 方法的衍生方法,故它的执行机理与 System.arraycopy() 方法相同。  所以 Arrays.copyOf() 方法对于基本数据类型来说是深拷贝,对引用类型来说是浅拷贝。

    四、对象拷贝(Object.clone)

      clone()比较特殊,对于对象而言,它是深拷贝,但是对于数组而言,它是浅拷贝。  首先讲一下对象的拷贝,它是深拷贝,大家可以用对象去测试一下。下面我们看一下它的源代码:

    1 protected native Object clone() throws CloneNotSupportedException;

      这里也有native关键字,所以也是底层的c语言实现的。  还要注意的是,这里修饰符是protected,也就是说,我们创建了一个Object类以后,是不能直接调用这个clone()方法的,因为protected关键字只允许同一个包内的类和它的子类调用,所以我们声明一个object类时,肯定不是同一个包内,所以就不能去调用它。  要调用这个方法,就需要我们写一个类,然后声明实现cloneable接口就好了,不需要去显示地声明继承于object,因为java中的类如果不显示说明父类的话,默认父类就是object。然后我们继承这个方法:

    1 @Override
    2 public Object clone() throws CloneNotSupportedException {
    3     // TODO Auto-generated method stub
    4     return super.clone();
    5 }

      这里需要是,为了能够在不同包内去调用这个方法,我们需要把这个权限升级为public。现在我们就可以调用这个类的clone()方法去拷贝我们的类了。

    五、数组拷贝

      对于数组而言,它不是简单的将引用赋值为另外一个数组引用,而是创建一个新的数组。但是我们知道,对于数组本身而言,它它的元素是对象的时候,本来数组每个元素中保存的就是对象的引用,所以,拷贝过来的数组自然而言也是对象的引用,所以对于数组对象元素而言,它又是浅拷贝。我们用以下代码验证一下:

     1 class Aby implements Cloneable{
     2     public int i;
     3     public Aby(int i) {
     4         this.i = i;
     5     }
     6     @Override
     7     public Object clone() throws CloneNotSupportedException {
     8         // TODO Auto-generated method stub
     9         return super.clone();
    10     }
    11 }
    12 public class Solution {
    13  
    14     public static void main(String[] args) throws CloneNotSupportedException {
    15         Aby aby1 = new Aby(1);
    16         Aby aby2 = (Aby) aby1.clone();
    17         aby1.i = 2;
    18         System.out.println(aby1.i); //2
    19         System.out.println(aby2.i); //1
    20  
    21         Aby[] arr = {aby1,aby2};
    22  
    23         Aby[] arr2 = arr.clone();
    24         arr2[0].i = 3;
    25         System.out.println(arr[0].i);   //3
    26         System.out.println(arr2[0].i);  //3
    27     }
    28 }
  • 相关阅读:
    PAT-字符串处理-A 1001 A+B Format (20分)
    PAT-字符串处理-B 1048 数字加密 (20分)
    数据库-第二章 关系数据库-2.3 关系的完整性
    数据库-第二章 关系数据库-2.2 关系操作
    数据库-第二章 关系数据库-2.1 关系数据结构及形式化定义
    IDLE打开Python报错 api-ms-win-crt-runtimel1-1-0.dll缺失的解决方案
    老毛桃pe安装系统
    LeetCode 213. House Robber II (动态规划)
    LeetCode 198. House Robber(DP)
    LeetCode 211. Add and Search Word
  • 原文地址:https://www.cnblogs.com/baichunyu/p/12966475.html
Copyright © 2011-2022 走看看