0

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?

lynxx
  • 544
  • 3
  • 18

1 Answers1

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

Andrey Tyukin
  • 43,673
  • 4
  • 57
  • 93
  • isn't the synthetic bridging method generated because, after erasure the class nodes setData = `setData(Object Data)` and the Class MyNode's setData = `setData( Integer Data)`. But they were meant to be Overriden. So compiler provides a `setData(Object Data)` in MyNode which would call `setData(Integer Data)` ? – lynxx Apr 21 '19 at 15:59
  • 1
    @lynxx I'm not sure what you wanted to ask in this comment. I think your problem is that you are confusing Java the Language and the JVM. These are two separate entities. JVM has its own notion of "method", and its own notion of "override". Java's "method" and "override" are closely related, but nonetheless different. Java's generics is one case where you see the difference: one single Java method mysteriously splits into two JVM methods. That's just a minor implementation detail. It might be useful occasionally when debugging certain errors, but is otherwise not even that important. – Andrey Tyukin Apr 21 '19 at 21:21
  • 1
    @lynxx Note that there are also other languages targeting the JVM. For example, Scala's "method" will again be slightly different, and because it has all kind of fancy stuff like singleton-objects, traits, and mixin composition, it will generate tons of synthetic JVM classes and JVM methods. If you look at the output of the Scala compiler, you'll often see that it generates fifty JVM `.class` files for a single Scala "class". This is entirely normal. Again, those are just some implementation details, that are usually not very important. – Andrey Tyukin Apr 21 '19 at 21:24
  • `After type erasure, the method signatures do not match. The Node method becomes setData(Object) and the MyNode method becomes setData(Integer). Therefore, the MyNode setData method does not override the Node setData method.(Oracle docs) ` This is what I was talking about in the point 2, that after erasure it the method looks like it is being `Overloaded` but in reality it should be `Overrided`, Hence compiler provides a bridging method to make the Overloaded method, Overrided. **Thanks for all your replies!!** – lynxx Apr 22 '19 at 03:01