2016-11-07 41 views
1

爲什麼這個問題是不是可能重複的How Arrays.asList(int[]) can return List<int[]>?。 這個問題並沒有真正回答我的具體情況,因爲我試圖找出在使用Arrays.copyOf時是否存在差異。看起來在數組差異。複製代碼

案例1:假設數組的深層副本

// Creating a integer array, populating its values 
    int[] src = new int[2]; 
    src[0] = 2; 
    src[1] = 3; 
    // Create a copy of the array 
    int [] dst= Arrays.copyOf(src,src.length); 
    Assert.assertArrayEquals(src, dst); 
    // Now change one element in the original 
    dst[0] = 4; 
    // Following line throws an exception, (which is expected) if the copy is a deep one 
    Assert.assertArrayEquals(src, dst); 

案例2: 這裏是哪裏的東西似乎是不可思議: 我試圖使用下面的方法(從書中逐字提起)是創建一個輸入數組參數副本的不可變列表視圖。這樣,如果輸入數組發生更改,返回列表的內容不會更改。

@SafeVarargs 
    public static <T> List<T> list(T... t) { 
    return Collections.unmodifiableList(new ArrayList<>(Arrays.asList(Arrays.copyOf(t, t.length)))); 
} 


int[] arr2 = new int[2]; 
    arr2[0] = 2; 
    arr2[1] = 3; 
    // Create an unmodifiable list 
    List<int[]> list2 = list(arr2); 

    list2.stream().forEach(s -> System.out.println(Arrays.toString(s))); 
    // Prints [2, 3] as expected   

    arr2[0] = 3; 

    list2.stream().forEach(s -> System.out.println(Arrays.toString(s)));  
    // Prints [3, 3] which doesn't make sense to me... I would have thought it would print [2, 3] and not be affected by my changing the value of the element. 

,我看到的是,在一個案例(案例1),Arrays.copyOf似乎是一個深拷貝,而在另一種情況下(案例2)的矛盾,這似乎是一種淺薄的。儘管我已經在創建我的不可修改列表中複製了數組,但原始數組的更改似乎已寫入列表。

有人能幫我解決這個矛盾嗎?

+4

這裏有很多問題。你正將'int []'傳遞給可變參數方法。它被包裝成一個'Object []',並傳遞給'copyOf'。因此'copyOf'複製了包含一個'int []'的Object []'。那個帶有一個'int []'的'Object []'然後被'asList'封裝到'List'中,只包含'int []'。然後,該列表中的元素(int [])被複制到一個新的'ArrayList'中,它一直是同樣的'int []'對象 –

+0

謝謝,Sotirios如果我正確理解你正在複製的內容是Object [](它包含int []),因此我實際上並沒有創建int []的副本,我想我將它傳遞給list()方法。在第一種情況下,它是直接操作在一個int []上,所以我看到的是對數組副本的更改 – Roberto

回答

0

首先,你的清單方法執行不必要的步驟中,您不需要copyOf操作,所以這裏有雲:

@SafeVarargs 
public static <T> List<T> list(T... t) { 
    return Collections.unmodifiableList(
     new ArrayList<>(Arrays.asList(t)) 
    ); 
} 

ArrayList的構造已經拷貝進入的列表,所以你是安全的那裏。

接下來,當您使用int []調用list()方法時,該數組被認爲是int []類型的單個元素,因爲T ...的類型擦除是Object .. 。和int是原始的。無法更改參數類型或執行instanceOf檢查並在方法內手動執行復制,您無法使方法在列表內進行深層複製。我認爲最明智的做法可能是將Arrays.copyOf()調用移到方法之外:

List<int[]> list2 = list(Arrays.copyOf(arr2)); 
+0

感謝Sean,這很有道理,我嘗試了一些替代建議以滿足我自己的好奇心,以及那些工作,再次感謝。 – Roberto