为什么这个问题不可能会重复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)中,它似乎是一个浅层副本。对原始数组的更改似乎已写入列表,即使我已在创建不可修改列表时复制了数组。
有人能帮助我解决这种差异吗?
答案 0 :(得分:0)
首先,你的list方法执行了一个不必要的步骤,你不需要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));