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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM