2017-04-05 358 views
1

我從System.arraycopy的某處讀取了基本數據類型和對象引用的淺拷貝。帶有基元和對象引用的System.arraycopy()淺拷貝或深度拷貝

是這樣,我開始了實驗,與下面的代碼

//trying with primitive values 
int a[] ={1,2,3}; 
int b[] = new int[a.length]; 
System.arraycopy(a,0,b,0,a.length); 
b[0] = 9; 
System.out.println(Arrays.toString(a)); 
System.out.println(Arrays.toString(b)); 
//now trying with object references 
Object[] obj1 = {new Integer(3),new StringBuffer("hello")}; 
Object[] obj2 = new Object[obj1.length]; 
System.arraycopy(obj1,0,obj2,0,obj1.length); 
obj1[1] = new StringBuffer("world"); 
System.out.println(Arrays.toString(obj1)); 
System.out.println(Arrays.toString(obj2)); 

輸出功率爲

[1, 2, 3] 
[9, 2, 3] 
[3, world] 
[3, hello] 

但我希望是

[1, 2, 3] 
[9, 2, 3] 
[3, world] 
[3, world] 

從上面的代碼,我瞭解System.arraycopy可以爲對象引用做深層複製 如果是這樣,怎麼obj1[0] == obj2[0]true

+0

「深副本元」。你怎麼能爲原語做一個深層次的拷貝呢?根據定義,它們並沒有更深層的意思。 – RealSkeptic

回答

2

你有一個誤解。

一旦你這樣做

obj1[1] = new StringBuffer("world"); 

obj1[1]更換參考。現在這兩個數組包含對不同對象的不同引用。

如果你想看到什麼被複制是實際的參考,你應該嘗試,而不是:

obj1[1].setLength(3); 

現在無論obj1[1]obj2[1]應包含字符串hel,因爲你沒有更換參考而是更改了內容

+0

現在我明白了。明確解釋.. –

1

System.arraycopy不淺拷貝,當用於非基本數組,這意味着它的副本Object引用。

因此在System.arraycopy(obj1,0,obj2,0,obj1.length);,obj1[0]==obj2[0]obj1[1]==obj2[1]之後,因爲兩個陣列都保持對相同的Object的引用。

一旦將新值分配給obj1[1],obj1[1]不再指與obj2[1]相同的StringBuffer實例。這就是爲什麼Arrays.toString(obj1)Arrays.toString(obj2)的輸出不同。

如果代替

obj1[1] = new StringBuffer("world"); 

你會寫

obj1[1].setLength(0); 
obj1[1].append("world"); 

兩個print語句將輸出[3, world],因爲這兩個陣列將仍然指向同一個StringBuffer實例。

0

不,這是淺拷貝的參考。

首先你創建一個new StringBuffer("hello")的引用,然後你做一個淺表副本。所以你有1 StringBuffer,但2引用它。

最後,您完全用new StringBuffer("world")替換其他參考。

+0

如果這樣'obj1 == obj2'應該給予真正的權利?但它給出了'false' –

+0

不,它們不是對** **數組的引用,所以當然返回false。 – Kayaman

0

我瞭解,System.arraycopy做深拷貝的對象 引用如果是這樣,如何OBJ1 [0] == obj2的[0]給出真正

不,你錯了,這不是」 t執行深層複製。因爲obj1[0] == obj2[0]在這兩個數組內都引用了相同的整數對象(即存儲在索引'0'處的數組中的引用),因此您得到的答案爲true。此外,您可以比較obj1[1] == obj2[1],它返回false,因爲兩個StringBuffer引用都不相同。

此外,另一點是System.arrayCopy只做一個淺拷貝(簡單地將參考/值從一個數組複製到另一個),您可以參考here

+0

'obj1 [0] == obj2 [0]比較整數值 - 實際上這是錯誤的。 'obj1 [0]'和'obj2 [0]'指向與arraycopy語句相同的'Integer'對象,這就是爲什麼'obj1 [0] == obj2 [0]'。如果在arraycopy語句之後添加'obj2 [0] = new Integer(3);'obj1 [0] == obj2 [0]'將不再成立,即使兩者仍然具有相同的值3)。 – Eran

+0

謝謝艾蘭,我改正了 – developer