擦除类型和桥接方法说明

Erasure type and Bridging Method clarification

以下代码取自泛型的 Oracle 文档 -

 class Node<T> {

    public T data;

    public Node(T data) { this.data = data; }

    public void setData(T data) {
        System.out.println("Node.setData");
        this.data = data;
    }
}

 class MyNode extends Node<Integer> {
    public MyNode(Integer data) { super(data); }

    public void setData(Integer data) {
        System.out.println("MyNode.setData");
        super.setData(data);
    }

     public static void main(String[] args) {
         MyNode mn = new MyNode(5);
         Node n = mn;            // A raw type - compiler throws an unchecked warning
         n.setData("Hello");
         Integer x = mn.data;  // Causes a ClassCastException to be thrown.
     }
}

我对这段代码的理解 -

问 - 方法 setData 是被覆盖还是重载?

我的理解 - 因为 MyNode 正在扩展 Node<Integer>,类型参数 T 的值被设置为 Integer

所以 class Node 有方法 setData(Integer data) as T= Integer class MyNode 有方法 setData(Integer data)

覆盖 因为签名相同。

问- setData 方法是否在擦除后被覆盖? 我的理解 -

我们擦除后 <T> set 方法变为 Node 变为 setData(Object data)

Mynode 的设置方法将是 - setData(Integer data) 因为没有类型参数,没有什么可以删除的。

但这是超载

问 - 我们想要重载或覆盖?

我的理解 - 从擦除之前定义的方法来看,我们想要覆盖

Q - 那么如何实现擦除后覆盖?

我的理解 - 通过 桥接方法。例如:

setData(Object data){
    setData((Integer) Data);
}

我的理解正确吗?

此外,class MyNode extends Node<Integer> 何时将 Integer 传递给 <T>?什么时候调用 super?

  1. 是的,方法 setData 被覆盖。
  2. 从用户的角度来看,它看起来好像 setData(T data)setData(Integer i) 覆盖了,即当您调用 setData(42) 时,它会用 "MyNode" 打印一些东西,而不是 "Node"

    在类型擦除方法签名级别,这将通过添加到 MyNode 的合成桥方法 setData(Object) 来实现,即如果您使用 [=19= 反编译 MyNode.class ],你会看到两个方法:

      public void setData(java.lang.Integer);
      public void setData(java.lang.Object);
    
  3. 语言规范说"override",我不知道为什么会有人想要其他东西。

  4. 不清楚你说的"achieve overriding after erasure"是什么意思。类型擦除发生在类型检查和确定什么覆盖什么之后。 "achieve" 没有任何意义,它只是事物工作的顺序(另请参阅 this comment)。覆盖原始 setData(Object) 的合成桥接方法看起来像你写的(小错别字):

    setData(Object data){
        setData((Integer) data);
    }
    

    至少 the documentation says 是这样。但这是一个synthetic方法,它是由编译器自动生成的。如果它出现在源代码中,它会给你编译错误。