0

I have some questions about bridge method creating. We can apply bridge technique for covariant overriding. Now consider example from the official help:

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;
    }
}

Let bridge method doesnt creating. Hence at run time class MyNode have two methods: setData(Integer) and setData(Object) where last is inheritated from Node. When we are calling setData(new Inetegr(5)) will called setData(Integer). If we write Object o= new Integer(5); setData(o); then setData(Object) will called. It is not true. So two questions:

  1. Am i understand the reason for introduction bridge method correctly?
  2. What is the necesseraly and enough conditions for bridge method creating?
Roman C
  • 49,761
  • 33
  • 66
  • 176
St.Antario
  • 26,175
  • 41
  • 130
  • 318
  • Hello - perhaps you will benefit greatly by reading the answer here: http://stackoverflow.com/questions/5007357/java-generics-bridge-method – Meesh Oct 06 '13 at 06:27

2 Answers2

2

Am i understand the reason for introduction bridge method correctly?

I think yes. If compiler didn't generate the bridge method, then the method in the subclass would be an overloaded version of super class method, and not the overridden version. As you already seem to understand.

What is the necesseraly and enough conditions for bridge method creating?

When you extend or implement a parameterized type, and type erasure changes the signature of the method in the super class.

If we write Object o= new Integer(5); setData(o); then setData(Object) will called. It is not true.

I don't understand what do you mean by that. You should test this behaviour on non-generic code. When a method is overloaded, then a method call is binded to which method is decided at compile-time, based on the declared type of the parameter you pass. Since the declared type in this case is Object, it will invoke setData(Object) version.

Rohit Jain
  • 209,639
  • 45
  • 409
  • 525
  • _I don't understand what do you mean by that_ Let we have raw type declarartion `Node m= new MyNode(5); Object o= new Integer(5); m.setData(o);`. Choosen a specific implementation of virtual method is determining at run time by type of object. But method `setData(Object)` doesnt overriden in `MyNode`. Hence method of `Node` will be invoked. – St.Antario Oct 06 '13 at 06:58
  • _When you extend or implement a parameterized type, and type erasure changes the signature of the method in the super class._ But in the case of covariant overriding we may haven't a parameterized types. But bridge method is creating. There are no another conditions to creat bridge method, isnt it? – St.Antario Oct 06 '13 at 07:05
1

This is a compiler which applies bridge technique, not us. In your case the compiler will insert the bridge here:

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

And this is why it is used:

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

Node does not have setData(Integer) it has setData(Object). MyNode bridge method setData(Object) overrides it. JVM detects that actual type of n is MyNode and calls MyNode.setData(Object) which will redirect to setData(Integer).

Another case when bridge methods are applied is covariant return type:

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

bridge is needed to actually override Object.clone. Note that in bytecode method signature includes return type.

Monolith
  • 1,067
  • 1
  • 13
  • 29
Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275