陣列協方差
物件陣列是協變的,這意味著就像 Integer
是 Number
的子類一樣,Integer[]
是 Number[]
的子類。這可能看起來很直觀,但可能導致令人驚訝的行為:
Integer[] integerArray = {1, 2, 3};
Number[] numberArray = integerArray; // valid
Number firstElement = numberArray[0]; // valid
numberArray[0] = 4L; // throws ArrayStoreException at runtime
雖然 Integer[]
是 Number[]
的子類,但它只能儲存 Integer
s,並且嘗試分配 Long
元素會丟擲執行時異常。
請注意,此行為對於陣列是唯一的,可以通過使用通用 List
來避免:
List<Integer> integerList = Arrays.asList(1, 2, 3);
//List<Number> numberList = integerList; // compile error
List<? extends Number> numberList = integerList;
Number firstElement = numberList.get(0);
//numberList.set(0, 4L); // compile error
所有陣列元素都不必共享相同的型別,只要它們是陣列型別的子類:
interface I {}
class A implements I {}
class B implements I {}
class C implements I {}
I[] array10 = new I[] { new A(), new B(), new C() }; // Create an array with new
// operator and array initializer.
I[] array11 = { new A(), new B(), new C() }; // Shortcut syntax with array
// initializer.
I[] array12 = new I[3]; // { null, null, null }
I[] array13 = new A[] { new A(), new A() }; // Works because A implements I.
Object[] array14 = new Object[] { "Hello, World!", 3.14159, 42 }; // Create an array with
// new operator and array initializer.
Object[] array15 = { new A(), 64, "My String" }; // Shortcut syntax
// with array initializer.