这为什么在Java中会导致运行时异常而不是编译时错误呢?
Object[] objects = new Object[10];
String[] strings = (String[])objects;
必须在运行时进行检查,因为存在以下情况:
public class Test {
public static void main(String[] args){
String[] stringsBase = {"aaa", "bbb", "ccc"};
Object[] objects = stringsBase;
String[] strings = (String[])objects;
System.out.println(strings[1]);
}
}
这是一个有效、可行的程序。如果没有进行流分析,编译器就不知道对象引用的是一个被创建为Object[]的数组,还是像这里一样被创建为String[]。
在该部分有关强制类型转换的前面规则中,给定编译时引用类型S(源)和编译时引用类型T(目标),如果遵循以下规则没有编译时错误,则从S到T存在强制类型转换。
...
如果S是数组类型SC[]
,即类型为SC的组件的数组:
...
- 如果T是数组类型TC
[]
,即类型为TC的组件的数组,则除非以下情况之一成立,否则会发生编译时错误:
- TC和SC是相同的基本类型。
- TC和SC都是引用类型,并且类型SC可以进行强制类型转换以变成TC。
Object
可以进行强制类型转换为String
。|T|
来表示类型T
的擦除,同时S :> T表示S和T之间存在超类型关系。 因此,“|S|<: |T|或|T|<: |S|”可以理解为“S的擦除是T的子类型、相同类型或超类型”。StringBuilder sb = new StringBuilder(); Object o = sb; Integer i = (Integer) o;
你能解释一下为什么吗?这似乎表明上面的情况不是一个特例...但我肯定是理解错了什么。 - jahroyObject
会让编译器感到困惑。如果您真的想理解它,请花时间仔细阅读JLS §5.5.1和5.5.2。 - Matt Ballnull
的变量时,Java会抛出NullPointerException?因为JLS规定必须这样做。”归根结底,关于Java为什么执行某些由JLS指定的操作的问题应该被解释为为什么JLS以特定的方式编写,否则就没有意义。 - Jules强制类型转换是Java提供的一项基本不安全的功能,旨在提高灵活性。如果编译器设置正确,则该代码会生成“未经检查”的警告。
String[]→Object[]→String[]
和例如String[]→Object[]→Integer[]
?这是一个引导性问题。当然,答案是JLS不要求编译器执行此类检查。 - Matt Ball