是否有一个特殊原因导致运行时异常而不是Java中的编译时错误?
Object[] objects = new Object[10];
String[] strings = (String[])objects;
答案 0 :(得分:4)
由于这种情况,检查必须在运行时完成:
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 []。
答案 1 :(得分:1)
因为这是语言规范定义的编译时行为。简短版本是Object[]
可以强制转换为String[]
而不生成编译 - 时间错误,因为Object
可以强制转换为String
而不会产生编译时错误。
答案很长,只是我引用JLS。来自the Java Language Specification § 5.5.1. Reference Type Casting:
给定编译时引用类型S(源)和编译时引用类型T(目标),如果由于以下规则而没有发生编译时错误,则从S到T存在转换转换。
...
如果S是数组类型SC[]
,即SC类型的组件数组:
...
- 如果T是数组类型TC
[]
,即TC类型的组件数组,则会发生编译时错误,除非满足以下条件之一:
- TC和SC是相同的原始类型。
- TC和SC是参考类型,SC类型可以进行铸造转换为TC。
通过前一个关于投射的相同部分的规则,Object
可以进行转换为String
s:
如果S是班级类型:
- 如果T是类类型,则为| S | &lt ;: | T |,或| T | <:| S |。否则,将发生编译时错误。
万一你想知道:
如果§5.5.1.
中的规则没有发生编译时错误,则引用类型的表达式可能会转换为另一个引用类型
请注意the JLS uses |T|
to denote the erasure of type T
以及S :> T indicates that the supertype relation holds between S and T.因此“| S |<:| T |,或| T |<:| S |”可以理解为“S的擦除是子类型,相同类型或T的超类型。”
答案 2 :(得分:0)
Casting是一个基本上不安全的功能,Java提供了灵活性。如果您的编译器设置正确调整,该代码会生成“未选中”警告。