将超类型的数组转换为子类型

时间:2013-04-12 02:09:35

标签: java arrays casting

是否有一个特殊原因导致运行时异常而不是Java中的编译时错误?

Object[] objects = new Object[10];
String[] strings = (String[])objects;

3 个答案:

答案 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提供了灵活性。如果您的编译器设置正确调整,该代码会生成“未选中”警告。