我刚读过“Effective Java”,我看到一句话说
因此,数组提供运行时类型安全性,但不提供编译时类型安全性,反之亦然
我对此并不十分清楚,即使在我阅读了所有给出的例子之后我也很困惑。任何人都可以向我解释这一点,感谢一百万。
答案 0 :(得分:3)
您无法在运行时更改数组(引用)的类型。但是你可以编译尝试的代码。
String[] strings = new String[1];
Object[] objects = strings;
objects[0] = new Integer(1); // RUN-TIME FAILURE
当您编译您的应用程序时,编译器不会抛出任何错误。
另一方面,如果你使用泛型,那么当你编译(构建)你的应用程序时,这会给你一个错误。
ArrayList<String> a = new ArrayList<String>();
a.add(5); //Adding an integer to a String ArrayList - compile-time failure
换句话说,您不需要实际运行应用程序并执行该部分代码来查找问题。
请注意,编译时故障比运行时故障更可取,因为您在将问题发布给用户之前就已发现问题(之后为时已晚)!
答案 1 :(得分:0)
对于泛型集合,此代码尝试将Integer放入String列表中,在第二行给出编译时错误:Cannot cast from List<String> to List<Object>
:
List<String> listOfStrings = new ArrayList<>();
List<Object> listAgain = (List<Object>)listOfStrings;
listAgain.add(123);
与数组的等效代码编译完美,因为将String数组用作Object数组是合法的。 (从技术上讲,数组是covariant。)
String[] arrayOfStrings = new String[10];
Object[] arrayAgain = arrayOfStrings;
arrayAgain[0] = 123;
但是,如果它实际上包含整数,它将不是一个有效的String数组,因此在运行时检查每个存储内容的操作。在运行时,它会以ArrayStoreException
爆炸。
答案 2 :(得分:0)
Java Array提供协变返回类型,而泛型不提供协变返回类型。
让我们用简单的例子来理解
public class GenericArrayDiff {
public static void main(String[] args) {
List<Vehicle> vehicleList = null;
List<Car> carList = null;
Vehicle[] vehicleArrays;
Car[] carArrays;
// illegal
carList = vehicleList;
// illegal
vehicleList = carList;
// illegal
carArrays = vehicleArrays;
// legal because array provides covariant return type
vehicleArrays = carArrays;
}
}
class Vehicle {
}
class Car extends Vehicle {
}