0

以下代码取自 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.
     }
}

我对这段代码的理解-

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

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

所以类Node有方法setData(Integer data) T= Integer 和类MyNode有方法setData(Integer data)

它是压倒一切的,因为签名是相同的。

Q- 即使在擦除之后,方法 setData 是否也会被覆盖? 我的理解 -

在我们擦除<T>set 方法之后,Node变成了,setData(Object data)

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

但这是超载的。

问 - 我们想要重载还是覆盖?

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

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

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

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

我的理解正确吗?

另外, class MyNode extends Node<Integer>什么时候Integer传递给<T>?什么时候调用超级?

4

1 回答 1

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

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

      public void setData(java.lang.Integer);
      public void setData(java.lang.Object);
    
  3. 语言规范说“覆盖”,我不知道为什么有人会想要别的东西。

  4. 目前尚不清楚“擦除后实现覆盖”是什么意思。类型擦除发生在类型检查并确定什么覆盖什么之后。没有什么可以“实现”的,这只是事情的工作顺序(另请参阅此评论)。覆盖原始的合成桥接方法setData(Object)看起来像你写的(直到小错别字):

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

    至少文档是这么说的。但这是一种合成方法,它是由编译器自动生成的。如果它出现在源代码中,它会给你编译错误。

于 2019-04-21T15:17:28.543 回答