MSS
MSS

Reputation: 563

Type Erasure tutorial on Java

I am reading the Generics trail on Oracle (Type Erasure) and I was not able to understand the following part.

The code snippets are shown below:

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

public class MyNode extends Node<Integer> {
    public MyNode(Integer data) { super(data); }

    public void setData(Integer data) {
        System.out.println("MyNode.setData");
        super.setData(data);
    }
}

The trail mentions the following:

Consider the following code:

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.

After type erasure, this code becomes:

MyNode mn = new MyNode(5);
Node n = (MyNode)mn;         // A raw type - compiler throws an unchecked warning
n.setData("Hello");
Integer x = (String)mn.data; // Causes a ClassCastException to be thrown.

Quoting from the same tutorial -

Here is what happens as the code is executed

I am not able to understand why trying to retrieve the data causes the exception. As far as my understanding goes shouldn't setting the data itself throw an exception (this is what happens on my compiler but since I am not using Oracle's compiler I am not sure which is right)?

If my understanding is right the class MyNode should have two methods :

void setData(Object); //bridge method
void setData(Integer);

So calling setData(Object) on Node should rightfully call the bridge method in MyNode which in turn calls setData(Integer) which is where the class-cast exception should be thrown. But Oracle' tutorial goes out of the way to say that this is not the case. So what is wrong with my understanding? Please help me understand.

Upvotes: 3

Views: 174

Answers (2)

Pedro
Pedro

Reputation: 1072

I came across this yesterday while reading the documentation. I opened this bug in the Oracle bug tracker and added this question as reference.

Upvotes: 0

If my understanding is right the class MyNode should have two methods
void setData(Object); //bridge method
void setData(Integer);

That is true. MyNode class will have above two methods.

Doing a javap on MyNode.class reveals it as well. See both the methods below highlighted between **

javap MyNode.class
Compiled from "MyNode.java"  
public class com.demo.generics.demo.MyNode extends com.demo.generics.demo.Node<j
ava.lang.Integer> {
  public com.demo.generics.demo.MyNode(java.lang.Integer);
  **public void setData(java.lang.Integer);**
  public static void main(java.lang.String[]);
  **public void setData(java.lang.Object);**
}

So calling setData(Object) on Node should rightfully call the bridge method in MyNode which in turn calls setData(Integer) which is where the class-cast exception should be thrown.

This is true as well. Calling it results in following exception:

Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
    at com.demo.generics.demo.MyNode.setData(MyNode.java:1)
    at com.demo.generics.demo.MyNode.main(MyNode.java:14)

MyNode.java:14 is where I am calling n.setData("Hello");

this is what happens on my compiler but since I am not using Oracle's compiler I am not sure which is right)?

This is not compiler dependent it should be same across.

Upvotes: 0

Related Questions