【问题标题】:Does upcasting not cause type erasure?向上转型不会导致类型擦除吗?
【发布时间】:2019-05-06 17:31:16
【问题描述】:

我最近遇到了在instanceof 检查后将object 向下转换为String 的代码。

Object obj = this.get(key);
if(obj instanceof String) {
    return (String) object;
}

我对它的工作原理有点困惑。我的理解是它不适用于泛型,因为类型擦除使实例没有对原始类的引用。此外,我的理解(由this answer 证实)是在运行时向上转换为Object 和使用泛型类型T 之间没有区别。这是否意味着instanceof 对泛型无效的唯一原因是由于列出了here 的编译时检查?

instanceof运算符的RelationalExpression操作数的类型必须是引用类型或者null类型;否则,会发生编译时错误。

如果在 instanceof 运算符后面提到的 ReferenceType 不表示可具体化的引用类型(第 4.7 节),则会出现编译时错误。

如果将 RelationalExpression 转换为 ReferenceType 将作为编译时错误被拒绝,则 instanceof 关系表达式同样会产生编译时错误。在这种情况下,instanceof 表达式的结果永远不会为真。

尽管如此,this question 中的答案似乎暗示运行时行为存在差异。是不是对象通常确实在运行时包含类型信息,但在泛型的情况下会被删除?在向上转换的情况下,该类型信息如何不会被删除?

希望有人能找出我的知识差距在哪里。我阅读了一些关于 instanceof here 的行为以试图澄清,但这有点超出我的理解,我希望得到更直接的答案。

【问题讨论】:

    标签: java generics


    【解决方案1】:

    对象总是知道它们到底是什么类型。

    类型擦除意味着泛型类型在编译代码中“丢失”。例如。 List<String> 编译为原始的List,逻辑上等价于List<Object>

    但是,将 String 分配给声明为 Object 的变量不会导致类型擦除,因为:

    1. 它不是泛型,所以类型擦除不适用。

    2. 对象知道它是一个String,而不管变量的声明类型如何。
      这就是为什么你可以问它:

      • 你是字符串吗? x instanceof String

      • 你是什么人? x.getClass()

    【讨论】:

    • 我想我跟着。所以boolean fn<T>(T x){ return x instanceof String;} 会起作用,而boolean fn<T>(T x){ return x instanceof T;} 会失败,因为 T 在运行时实际上不存在(它总是Object)?
    • @Kyle 是正确的。该代码将无法编译。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-05
    • 2020-04-17
    相关资源
    最近更新 更多