天天看點

數組的四種複制方法

java數組拷貝主要有四種方法,分别是循環指派,System.arraycopy(),Arrays.copyOf()(或者Arrays.copyOfRange)和clone()方法。下面分别介紹一下這幾種拷貝。

循環拷貝(速度相對比較慢)

循環拷貝其實沒什麼好說的啦,就是用一個for循環進行元素的逐個拷貝,進行深拷貝或者淺複制這個大家可以自己把握。

System.arraycopy(淺拷貝)

這個是系統提供的拷貝方式,也是我們推薦使用的拷貝方式,它是淺拷貝,也就是說對于非基本類型而言,它拷貝的是對象的引用,而不是去建立一個新的對象。通過它的代碼我們可以看到,這個方法不是用java語言寫的,而是底層用c或者c++實作的,因而速度會比較快。

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

通過源代碼我們可以看到,關鍵字native說明它不是用java語言寫的,而是調用其他語言的代碼。

Arrays.copyOf(淺拷貝)

這個方法也是淺拷貝,為什麼呢?我們看一下它的源代碼就知道了。

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

實際上它調用的就是System.arraycopy,是以肯定也是淺拷貝。

Object.clone

clone()比較特殊,對于對象而言,它是深拷貝,但是對于數組而言,它是淺拷貝。

對象拷貝

首先講一下對象的拷貝,它是深拷貝,大家可以用對象去測試一下。下面我們看一下它的源代碼:

protected native Object clone() throws CloneNotSupportedException;           

這裡也有native關鍵字,是以也是底層的c語言實作的。

還要注意的是,這裡修飾符是protected,也就是說,我們建立了一個Object類以後,是不能直接調用這個clone()方法的,因為protected關鍵字隻允許同一個包内的類和它的子類調用,是以我們聲明一個object類時,肯定不是同一個包内,是以就不能去調用它。

要調用這個方法,就需要我們寫一個類,然後聲明實作cloneable接口就好了,不需要去顯示地聲明繼承于object,因為java中的類如果不顯示說明父類的話,預設父類就是object。然後我們繼承這個方法:

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

這裡需要是,為了能夠在不同包内去調用這個方法,我們需要把這個權限更新為public。現在我們就可以調用這個類的clone()方法去拷貝我們的類了。

數組拷貝

對于數組而言,它不是簡單的将引用指派為另外一個數組引用,而是建立一個新的數組。但是我們知道,對于數組本身而言,它它的元素是對象的時候,本來數組每個元素中儲存的就是對象的引用,是以,拷貝過來的數組自然而言也是對象的引用,是以對于數組對象元素而言,它又是淺拷貝。我們用以下代碼驗證一下:

class Aby implements Cloneable{
    public int i;
    public Aby(int i) {
        this.i = i;
    }
    @Override
    public Object clone() throws CloneNotSupportedException {
        // TODO Auto-generated method stub
        return super.clone();
    }
}

public class Solution {

    public static void main(String[] args) throws CloneNotSupportedException {
        Aby aby1 = new Aby(1);
        Aby aby2 = (Aby) aby1.clone();
        aby1.i = 2;
        System.out.println(aby1.i); //2
        System.out.println(aby2.i); //1

        Aby[] arr = {aby1,aby2};

        Aby[] arr2 = arr.clone();
        arr2[0].i = 3;
        System.out.println(arr[0].i);   //3
        System.out.println(arr2[0].i);  //3
    }
}