Java强制转换操作符如何工作?

Jam*_*hon 11 java jvm casting

我试图在Java中调试涉及ClassCastException的问题.为了解决这个问题,我需要知道当我从Object转换为特定类型时会发生什么.任何人都可以向我解释Java转换运算符如何在Java级别和JVM级别上运行?

Mic*_*ers 10

JLS不够好?

转换转换应用于转换运算符的操作数(第15.16节):操作数表达式的类型必须转换为转换运算符显式命名的类型.转换上下文允许使用:

  • 身份转换(§5.1.1)
  • 扩展的原始转换(第5.1.2节)
  • 缩小的原始转换(第5.1.3节)
  • 扩展引用转换(第5.1.5节),可选地后跟未经检查的转换(第5.1.9节)
  • 缩小的引用转换(第5.1.6节),可选地后跟未经检查的转换
  • 拳击转换(§5.1.7)
  • 拆箱转换(第5.1.8节).

实际上,也许这部分更相关:

将编译时引用类型S的值转换为编译时引用类型T的编译时合法性的详细规则如下:

  • 如果 S是类类型:
    • 如果T是类类型,则为| S | <:| T |,或| T | <:| S |; 否则会发生编译时错误.此外,如果存在的超类型XŤ,和超类型ÿ小号,使得两个Xÿ是可证明不同参数化类型(§4.5),并且的擦除Xÿ是相同的,编译时发生错误.
    • 如果T是接口类型:

      • 如果 小号不是final 类(§8.1.1),然后,如果存在的超类型 XŤ,和超类型 ÿ小号,使得两个 Xÿ是可证明不同参数化类型,那的擦除XY 是相同的,发生编译时错误.否则,强制转换在编译时总是合法的(因为即使 S没有实现T,S的子类也可能).
      • 如果S是一个 final类(第8.1.1节),则S必须实现T,否则会发生编译时错误.

    • 如果Ť 是一种类型的变量,那么该算法递归地应用,使用上界的Ť代替Ť.
    • 如果T是数组类型,则S必须是类Object,否则会发生编译时错误.
  • 如果S是接口类型:
    • 如果T是数组类型,则T必须实现S,否则会发生编译时错误.
    • 如果Ť是一个类型不 final(§8.1.1),然后,如果存在的超类型 XŤ,和超类型 ÿ小号,使得两个 Xÿ是可证明不同参数化类型,那的擦除XY 相同,发生编译时错误.否则,强制转换在编译时总是合法的(因为即使 T没有实现S,也可能是T的子类).
    • 如果T是一个类型final,那么:
      • 如果S不是参数化类型或原始类型,则T必须实现S,并且静态地知道强制转换是正确的,否则会发生编译时错误.
      • 否则, S是参数化类型,它是某种泛型类型声明G的调用,或者是对应于泛型类型声明G的原始类型.然后必须存在一个超类型XŤ,使得X是的调用ģ,或发生编译时间错误.此外,如果SX 可证明是不同的参数化类型,则发生编译时错误.
  • 如果小号是一种类型的变量,那么该算法递归地应用,使用上界的小号代替 小号.
  • 如果 S是数组类型SC [],即SC类型的组件数组:
    • 如果T是类类型,那么如果T不是 Object,则发生编译时错误(因为 Object是唯一可以为其分配数组的类类型).
    • 如果T 是接口类型,则会发生编译时错误,除非 T是类型 java.io.Serializable或类型Cloneable,是数组实现的唯一接口.
    • 如果T 是一个类型变量,那么:
      • 如果T的上限是 Object或者类型 java.io.Serializable或类型Cloneable,或者通过递归地应用这些规则可以合法地转换为S的类型变量,那么转换是合法的(虽然未经检查).
      • 如果T的上限是数组类型 TC [],则发生编译时错误,除非通过递归应用这些编译时规则进行转换,可以将类型SC []强制转换为TC [].
      • 否则,发生编译时错误.
    • 如果T是数组类型TC [],即TC类型的组件数组,则会发生编译时错误,除非满足下列条件之一:

    • TCSC是相同的原始类型.
    • TCSC是引用类型,类型 SC可以通过递归应用这些编译时规则进行转换来转换为TC.

现在完全清楚,不是吗?:d

换句话说,如果不了解有关您问题的更多详细信息,这是我能做的最好的事情.


djn*_*jna 6

类转换神秘化的一个可能原因是,不仅类型必须匹配,而且它们必须由相同的类加载器加载.

您不仅可以转储类型层次结构,还可以转储每个类的类加载器的标识.

这些问题在应用程序风格的环境中并不罕见,其中应用程序代码和基础结构代码是故意隔离的 - 例如,如果系统类意外地包含在应用程序JAR中,您可以在JVM中拥有两个"相同"类的副本,并且生活变得混乱