Java类型擦除:转换插入规则?
Java Type Erasure: Rules of cast insertion?
Java tutorial on type erasure 似乎没有详细说明编译器强制转换插入的具体规则。有没有大神能解释一下教程中详述的导致转换的具体规则(转载如下):
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.
具体来说,我想知道是什么规则导致插入 (MyNode)
和 (String)
。什么时候插入演员表,如何选择演员表的类型?
MyNode mn = new MyNode(5);
- 将创建一个
MyNode
的实例,它将接口 Node
的通用类型 T
定义为 Integer
- 转换:开发人员不需要转换,编译器没有添加转换
Node n = (MyNode)mn;
- 这基本上会告诉编译器忘记泛型类型
T
并使用接口 Node
完全没有泛型,这将产生以下结果:想象一下泛型类型 T
被视为 java.lang.Object
- 转换:开发人员不需要转换,编译器没有添加转换
n.setData("Hello");
- 将允许您添加任何类型的 ob 对象 因为 T 被视为对象(
String
、Integer
、数组、任何其他对象)
- 转换:开发人员不需要转换,编译器没有添加转换
Integer x = mn.data;
nm.data
应该 return 一个 Integer
类型,因为 Integer
在 MyNode
[=91] 中定义为通用类型参数 T
=]
- 但是因为您使用了允许您添加
String
的原始类型,所以 nm.data
包含一个 String
实例
- 转换:开发人员不需要转换,但是编译器会在幕后为您添加转换为 Integer 并且由于类型不匹配,您将得到
ClassCastException
当调用
时,ClassCastException
将是 throw
n.setData("Hello");
这是因为编译器构建桥接方法来保留多态性。桥接方法如下所示:
public void setData(Object data) {
setData((Integer)data); //the exception is thrown here
}
由于字符串实例无法转换为 Integer
,因此会抛出 ClassCastException
。
您可以阅读桥接方法 here。
Java tutorial on type erasure 似乎没有详细说明编译器强制转换插入的具体规则。有没有大神能解释一下教程中详述的导致转换的具体规则(转载如下):
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.
具体来说,我想知道是什么规则导致插入 (MyNode)
和 (String)
。什么时候插入演员表,如何选择演员表的类型?
MyNode mn = new MyNode(5);
- 将创建一个
MyNode
的实例,它将接口Node
的通用类型T
定义为Integer
- 转换:开发人员不需要转换,编译器没有添加转换
- 将创建一个
Node n = (MyNode)mn;
- 这基本上会告诉编译器忘记泛型类型
T
并使用接口Node
完全没有泛型,这将产生以下结果:想象一下泛型类型T
被视为java.lang.Object
- 转换:开发人员不需要转换,编译器没有添加转换
- 这基本上会告诉编译器忘记泛型类型
n.setData("Hello");
- 将允许您添加任何类型的 ob 对象 因为 T 被视为对象(
String
、Integer
、数组、任何其他对象) - 转换:开发人员不需要转换,编译器没有添加转换
- 将允许您添加任何类型的 ob 对象 因为 T 被视为对象(
Integer x = mn.data;
nm.data
应该 return 一个Integer
类型,因为Integer
在MyNode
[=91] 中定义为通用类型参数T
=]- 但是因为您使用了允许您添加
String
的原始类型,所以nm.data
包含一个String
实例 - 转换:开发人员不需要转换,但是编译器会在幕后为您添加转换为 Integer 并且由于类型不匹配,您将得到
ClassCastException
当调用
时,ClassCastException
将是 throw
n.setData("Hello");
这是因为编译器构建桥接方法来保留多态性。桥接方法如下所示:
public void setData(Object data) {
setData((Integer)data); //the exception is thrown here
}
由于字符串实例无法转换为 Integer
,因此会抛出 ClassCastException
。
您可以阅读桥接方法 here。