2013-10-06 53 views
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; 
    } 
} 

让bridge方法不创建。因此,在运行时,类MyNode有两种方法:setData(Integer)setData(Object),其中最后一个从Node继承。当我们拨打setData(new Inetegr(5))时会拨打setData(Integer)。如果我们写Object o= new Integer(5); setData(o);那么将调用setData(Object)。这不是真的。 所以有两个问题:

  1. 我明白导入桥接方法正确的原因吗?
  2. 创建桥梁方法的必要条件和足够的条件是什么?
+0

你好 - 也许你会从这里阅读答案大大受益:http://stackoverflow.com/questions/5007357/java-generics-bridge-method – Meesh

回答

2

我明白引入桥接方法的理由吗?

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

创建桥梁方法的必要条件和足够的条件是什么?

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

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

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

+0

_我不明白你说的是什么意思_让我们有原始类型声明'Node m = new MyNode(5);对象o =新整数(5); m.setData(O);'。选择虚拟方法的具体实现是在运行时按对象类型来确定。但'setData(Object)'方法在'MyNode'中没有重载。因此'Node'的方法将被调用。 –

+0

_扩展或实现参数化类型时,输入erasure会更改超类中方法的签名。但在协变覆盖的情况下,我们可能没有参数化类型。但桥梁方法正在创建。没有其他条件可以创建桥梁方法,不是吗? –

1

这是编译谁应用桥技术,而不是我们。根据你的情况,编译器会在这里插入桥

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

,这就是为什么它被用来

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

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

施加桥方法时的另一种情况是协变返回类型需要

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

桥实际重写Object.clone。请注意,在字节码方法签名包括返回类型