java - 为什么在运行时对数组组件的赋值进行类型检查?
问题描述
我正在阅读 Effective 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() 分配给数组 [0] 时,编译器不考虑实际的数组对象 (B[10])。是因为编译器没有可用的信息吗?
解决方案
编译器可以在您发布的代码中检测到该错误,但一般情况下不会。
由于协方差,B[]
可以将 分配给A[]
第一行中的变量。如果将该数组传递给在第二行中执行赋值的方法,编译器将无法检测到数组的原始类型。
因此,这两行在编译时都是有效的。
推荐阅读
- php - PHP/mysql 计算重复项并输出为数字
- android - 如何获得 JSON 响应的某个字段?
- node.js - Discord.js - 记录通道删除给出错误“UnhandledPromiseRejectionWarning:TypeError:无法读取未定义的属性'名称'”
- swift - 用函数初始化结构值
- css - Bootstrap 4将文本左对齐,如表格
- excel - 如何仅使用 VB 脚本单击 Excel 自定义选项卡控件,以便我可以在 UFT 中使用它
- javascript - 如何将道具传递给一个 React 类到另一个 React 类?
- jquery - 酒保软件 HTML 条形码未显示在标签预览中
- python - 为什么这个 python 函数不能读取全局变量?
- atom-editor - 在离线时安装具有依赖项的原子包