问题
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?
回答1:
MyNode mn = new MyNode(5);
- will create an instance of
MyNode
which defines the generic typeT
of interfaceNode
asInteger
- casting: no casting necessary by developer, no casts added by compiler
- will create an instance of
Node n = (MyNode)mn;
- this will basically tell the compiler forget about the generic type
T
and use the interfaceNode
completely without generics which will have the following consequence: imagine generic typeT
to be treated asjava.lang.Object
- casting: no casting necessary by developer, no casts added by compiler
- this will basically tell the compiler forget about the generic type
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
- will allow you to add any kind ob object because T is treated as Object (
Integer x = mn.data;
nm.data
should return anInteger
type asInteger
is defined as generic type argumentT
in theMyNode
class- however because you used raw types which allowed you to add a
String
instead, thenm.data
holds aString
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
回答2:
The ClassCastException
would be throw
when a call is made to
n.setData("Hello");
This is because the compiler builds bridge methods to preserve polymorphism. The bridge method will look like:
public void setData(Object data) {
setData((Integer)data); //the exception is thrown here
}
since an instance of a string cannot be converted to Integer
, the ClassCastException
would be thrown.
You can read about bridge methods here.
来源:https://stackoverflow.com/questions/29587502/java-type-erasure-rules-of-cast-insertion