当前位置: 首页 > 面试题库 >

Java强制转换运算符如何工作?

单勇
2023-03-14
问题内容

我正在尝试调试Java中涉及ClassCastException的问题。为了解决该问题,我需要知道从Object转换为特定类型时发生了什么。
谁能向我解释Java Cast操作符如何在Java级别和JVM级别工作?


问题答案:

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 不实现 TS 的子类也可能实现)。
    • 如果 S 是一个 final类(第8.1.1节),则 S 必须实现 T ,否则会发生编译时错误。

    • 如果 T 是类型变量,则使用 T 的上限代替 T 递归地应用此算法。

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

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

换句话说,这是我不知道有关您的问题的更多详细信息所能做的最好的事情。



 类似资料:
  • C++ 运算符 强制转换运算符是一种特殊的运算符,它把一种数据类型转换为另一种数据类型。强制转换运算符是一元运算符,它的优先级与其他一元运算符相同。 大多数的 C++ 编译器都支持大部分通用的强制转换运算符: (type) expression 其中,type 是转换后的数据类型。下面列出了 C++ 支持的其他几种强制转换运算符: const_cast<type> (expr): const

  • 问题内容: 我很难理解一些代码,这些代码显示了一个示例,该示例如何将Java中的double转换为byte [],反之亦然。 这是用于将双精度型转换为byte []的代码: 这是用于将byte []转换为double的代码: 好的,这是我不太了解的部分。 似乎强制转换发生在实际的按位运算之前,因为作者说 该表达式将把字节放在长[…]处,然后应用mask删除java施加的符号 在实际转换之前,如何将

  • 我有一些我无法控制的代码。此代码接受一个对象参数,并尝试将其转换为编译时已知的类型,如下所示: 在C#中是否可以设计一个自定义类(不是从KnownType派生的),该类可以作为参数传递给上述代码,并通过上述代码转换为,前提是可以使用其成员方法将自身转换为: 我曾尝试实现这样的自定义转换运算符: 但是它不起作用(它没有被使用)。假设转换运算符仅在编译时已知源类型、目标类型和转换运算符时才起作用,这是

  • JLS说 编辑:如果操作数已经使用转换运算符转换为不同的(较小的)类型,那么操作数是否经历数字提升(一元/二进制)?如果是这种情况,您将如何解释具有字节变量的表达式,因为在强制转换之后,字节结果可能会根据数字提升转换为int?

  • 问题内容: 直到今天,我还以为例如: 只是以下方面的捷径: 但是,如果我们尝试这样做: 然后;将不会编译,但;会编译良好。 这是否意味着实际上;是类似这样的捷径 ? 问题答案: 与这些问题一样,JLS保留了答案。在这种情况下,第1.5.26.2节“复合赋值运算符”。摘录: 形式的复合赋值表达式等效于,其中T是的类型,不同之处在于该表达式E1仅被评估一次。 §15.26.2中引用的示例 以下代码正确

  • 问题内容: 我想将一些转换成这样的运算符: 如何将变量操作转换为运算符? 问题答案: 您可以尝试以下方法: