javagenericserasurejava-bridge-method

Erasure type and Bridging Method clarification


The code following is taken from Oracle documentation of generics -

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

My understanding of this code -

Q - is method setData overrided or overloaded?

my under standing - because MyNode is extending Node<Integer>, the value of type parameter T is set to Integer.

so class Node has method setData(Integer data) as T= Integer and class MyNode has method setData(Integer data).

It is overriding as signature is same.

Q- is the method setData Overrided even after Erasure? My understanding -

after we erase <T> the set method becomes in Node becomes, setData(Object data)

and the set method of Mynode will be - setData(Integer data) as there is no type parameter, nothing to remove.

But this is overloading.

Q - we wanted overloading or overriding?

My understanding - by the looks of methods defined before erasure, we wanted overriding.

Q - So how to achieve Overiding after Erasure?

My understanding - By Bridging Method. for example:

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

Is my understanding correct?

Also, class MyNode extends Node<Integer> when does Integer is passed down to <T> ? when super is called?


Solution

    1. Yes, the method setData is overridden.
    2. From the point of view of the user, it will look as if setData(T data) is overridden by setData(Integer i), i.e. when you invoke setData(42), it will print something with "MyNode", not with "Node".

      On the level of type erased method signatures, this will be achieved by a synthetic bridge method setData(Object) added to MyNode, i.e. if you decompile MyNode.class with javap, you will see two methods:

        public void setData(java.lang.Integer);
        public void setData(java.lang.Object);
      
    3. The language spec says "override", I don't know why anyone would want something else.

    4. It's not clear what you mean by "achieve overriding after erasure". The type erasure comes after the type checking and determining what overrides what. There is nothing to "achieve", it's just the order in which things work (see also this comment). The synthetic bridging method that overrides the original setData(Object) looks like what you wrote (up to minor typos):

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

      at least that's what the documentation says. But this is a synthetic method, it is generated by the compiler automatically. If it appeared in the source code, it would give you compilation errors.