简体   繁体   中英

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

  • n.setData("Hello"); causes the method setData(Object) to be executed on the object of class MyNode. (The MyNode class inherited setData(Object) from Node.)
  • In the body of setData(Object), the data field of the object referenced by n is assigned to a String.
  • The data field of that same object, referenced via mn, can be accessed and is expected to be an integer (since mn is a MyNode which is a Node.
  • Trying to assign a String to an Integer causes a ClassCastException from a cast inserted at the assignment by a Java compiler.

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.

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM