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?
The
ClassCastException
would bethrow
when a call is made toThis is because the compiler builds bridge methods to preserve polymorphism. The bridge method will look like:
since an instance of a string cannot be converted to
Integer
, theClassCastException
would be thrown.You can read about bridge methods here.
MyNode mn = new MyNode(5);
MyNode
which defines the generic typeT
of interfaceNode
asInteger
Node n = (MyNode)mn;
T
and use the interfaceNode
completely without generics which will have the following consequence: imagine generic typeT
to be treated asjava.lang.Object
n.setData("Hello");
String
,Integer
, array, anything else)Integer x = mn.data;
nm.data
should return anInteger
type asInteger
is defined as generic type argumentT
in theMyNode
classString
instead, thenm.data
holds aString
instanceClassCastException