为什么要在运行时完成对数组组件分配的类型检查?

时间:2019-03-01 17:11:16

标签: java arrays types

我正在阅读有效Java的第28条,其中作者写道

  

数组与泛型之间的第二个主要区别是数组   化了[JLS,4.7]。这意味着数组知道并强制执行它们   元素类型在运行时。

但是为什么在运行时? 例如,考虑两个类,其中A是B的父级

public static void main(String[] args) {
        A[] array = new B[10];
        array[0] = new A();
}

此代码引发ArrayStoreException。在我看来,编译器可能已经识别出错误。那么为什么编译器让它通过。是因为JLS不想编译器那么聪明(慢)吗?。

  

JLS 10.5 对于类型为A []的数组,其中A为引用类型,   在运行时检查对数组组件的分配以   确保分配的值可分配给组件。

现在我的理解是

  • 在上面的示例中,在编译时(以及在运行时)数组变量的类型为A []
  • 编译器的职责是确保仅将A []或A []的某些子类型分配给数组变量。
  • 数组(array [0])的组件相同,编译器将仅检查分配的值是A还是A的某些子类型。

当将A()分配给array [0]时,编译器为什么不考虑实际的数组对象(B [10])。 是因为编译器没有可用的信息吗?

2 个答案:

答案 0 :(得分:1)

编译器可以在您发布的代码中检测到错误,但通常情况下无法检测到。

由于协方差,df = pd.read_excel(my_excel_file, na_values=[''], dtype=object) 可以在第一行中分配给B[]变量。如果将数组传递给在第二行中执行赋值的方法,则编译器将无法检测到数组的原始类型。

因此,这两行在编译时均有效。

答案 1 :(得分:1)

  

在我看来,编译器可能已识别出错误。

好吧;编译器无法确定运行时array的实际类型。

让我们举一个简单的例子,

array = myRandomFunction()>0 ? new A[10] : new B[10];

然后array的实际类型可以是A[]B[],并且编译器无济于事。


考虑一下;这类似于NullPointerException的情况:编译器不会抱怨以下内容(即使总是在运行时抛出)

Object a=null;
a.toString();