泛型桥接法——论多态

Laz*_*Boy 4 java generics

我试图理解桥接方法创建的概念,并被困在 Oracle Java Docs 上给出的示例中。

下面是例子供参考

给出以下两个类:

public class Node<T> {

    private T data;

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

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

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

    public void setData(Integer data) {
        System.out.println("MyNode.setData");
        super.setData(data);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后写到由于类型擦除,编译后的类应该如下:

类型擦除后,Node 和 MyNode 类变为:

public class Node {

    private Object data;

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

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

public class MyNode extends Node {

    public MyNode(Integer data) { super(data); }

    public void setData(Integer data) {
        System.out.println(Integer data);
        super.setData(data);
    }
}
Run Code Online (Sandbox Code Playgroud)

所以为了保持多态性,在 Class MyNode 中输入了一个桥接方法

class MyNode extends Node {

    // Bridge method generated by the compiler
    //
    public void setData(Object data) {
        setData((Integer) data);
    }

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

    // ...
}
Run Code Online (Sandbox Code Playgroud)

下面是我的问题,它是如何解决多态性的?假设我使用以下代码调用 setData

MyNode mn = new MyNode(5);
mn.setData(new Integer(6)); 
Run Code Online (Sandbox Code Playgroud)
  1. 从 MyNode、setData(Integer data) 或 setData(Object data) 调用哪个方法?

  2. 当从 MyNode 类中的 setData(Integer data) 调用 super.setData(data) 时,这是如何解决的,因为由于类型擦除,超类节点中没有 setData(Integer int)?似乎解释过的多态问题在编译器插入 Bridge Method 后仍然存在。任何帮助/解释都非常感谢。谢谢!!

Hol*_*ger 6

如果你有类似的代码

MyNode mn = new MyNode(5);
mn.setData(new Integer(6));
Run Code Online (Sandbox Code Playgroud)

它将调用setData(Integer)您明确声明的方法。诸如以下代码的事情变得更有趣:

Node<Integer> mn = new MyNode(5);
mn.setData(new Integer(6));
Run Code Online (Sandbox Code Playgroud)

由于在类型擦除后,该类Node没有方法setData(Integer),因此setData(Object)将调用该方法。这就是桥接方法发挥作用的地方:

为了调用所需的方法MyNode.setData(Integer)而不是Node.setData(Object)(这是预期的多态性),该类MyNode具有一个合成桥方法,该方法覆盖setData(Object)并调用setData(Integer).