javagenericscastingerasure

Java Type Erasure: Rules of cast insertion?


The Java tutorial on type erasure doesn't seem to detail the specific rules of cast insertion by the compiler. Can someone please explain the specific rules that cause the transformation detailed by the tutorial (reproduced 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);
    }
}

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.

Specifically, I'm wondering what rules cause the insertion of (MyNode) and (String). When is a cast inserted, and how is the type chosen for the cast?


Solution

    1. MyNode mn = new MyNode(5);

      • will create an instance of MyNode which defines the generic type T of interface Node as Integer
      • casting: no casting necessary by developer, no casts added by compiler
    2. Node n = (MyNode)mn;

      • this will basically tell the compiler forget about the generic type T and use the interface Node completely without generics which will have the following consequence: imagine generic type T to be treated as java.lang.Object
      • casting: no casting necessary by developer, no casts added by compiler
    3. n.setData("Hello");

      • will allow you to add any kind ob object because T is treated as Object (String, Integer, array, anything else)
      • casting: no casting necessary by developer, no casts added by compiler
    4. Integer x = mn.data;

      • nm.data should return an Integer type as Integer is defined as generic type argument T in the MyNode class
      • however because you used raw types which allowed you to add a String instead, the nm.data holds a String instance
      • casting: no casting necessary by developer, however the compiler will add casts to Integer behind the scenes for you and because of type mismatch, you will get the ClassCastException