0

我对桥接方法创建有一些疑问。我们可以将桥接技术应用于协变覆盖。现在考虑官方帮助中的示例:

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");
         this.data=data;
    }
}

让桥方法不创建。因此,在运行时类有MyNode两种方法:last 继承自. 当我们打电话时会打电话。如果我们写然后会调用。这不是真的。所以两个问题:setData(Integer)setData(Object)NodesetData(new Inetegr(5))setData(Integer)Object o= new Integer(5); setData(o);setData(Object)

  1. 我是否正确理解引入桥接方法的原因?
  2. 建立桥梁方法的必要和充分条件是什么?
4

2 回答 2

2

我是否正确理解引入桥接方法的原因?

我想是的。如果编译器没有生成桥方法,那么子类中的方法将是超类方法的重载版本,而不是重载版本。正如你似乎已经理解的那样。

建立桥梁方法的必要和充分条件是什么?

当您扩展或实现参数化类型时,类型擦除会更改超类中方法的签名。

如果我们写Object o= new Integer(5); setData(o);然后setData(Object)会调用。这不是真的。

我不明白你这是什么意思。您应该在非泛型代码上测试此行为。当方法被重载时,方法调用绑定到哪个方法,在编译时根据您传递的参数的声明类型决定。由于在这种情况下声明的类型是Object,它将调用setData(Object)版本。

于 2013-10-06T06:26:11.040 回答
1

这是一个应用桥接技术的编译器,而不是我们。在您的情况下,编译器将在此处插入桥:

class MyNode extends Node<Integer> {
  public void setData(Object data) {
     setData((Integer) data);
  }
...

这就是使用它的原因:

    Node<Integer> n = new MyNode();
    n.setData(1);

节点没有 setData(Integer) 它有 setData(Object)。MyNode 桥方法 setData(Object) 覆盖它。JVM 检测到 n 的实际类型是 MyNode 并调用 MyNode.setData(Object) 将重定向到 setData(Integer)。

应用桥接方法的另一种情况是协变返回类型:

class X implements Cloneable {
    @Override
    public X clone() {
         ...
    }

bridge 需要实际覆盖Object.clone。请注意,字节码方法签名包括返回类型。

于 2013-10-06T06:39:31.357 回答