java - 阅读 Core Java 第 11 版时关于 **Type Erasure 机制** 的问题
问题描述
这是作者在书中提供的关于泛型编程的代码示例:
public class Pair<T>
{
private T first;
private T second;
public Pair() { first = null; second = null; }
public Pair(T first, T second) { this.first = first; this.second = second; }
public T getFirst() { return first; }
public T getSecond() { return second; }
public void setFirst(T newValue) { first = newValue; }public void setSecond(T newValue) {
second = newValue; }
}
然后作者介绍了类型擦除机制
无论何时定义泛型类型,都会自动提供相应的原始类型。原始类型的名称只是泛型类型的名称,类型参数已删除。类型变量被删除并替换为它们的边界类型(或例如,对象的原始类型用于无边界变量)。
您的程序可能包含不同类型的擦除将它们全部转换为原始 Pair ,例如
Pair<String>
orPair<LocalDate>
,但擦除将它们全部转换为原始 Pair 类型。
所以对于 的情况class Pair<T>
,擦除后它变成下面的raw Pair 类型:
public class Pair
{
private Object first;private Object second;
public Pair(Object first, Object second)
{
this.first = first;
this.second = second;
}
public Object getFirst() { return first; }
public Object getSecond() { return second; }
public void setFirst(Object newValue) { first = newValue; }
public void setSecond(Object newValue) { second = newValue; }
}
所以如果我们运行代码,打印 TURE
Pair<Integer> p = new Pair<Integer>(1, 2);
Pair<String> s = new Pair<String>("a", "b");
System.out.println(p.getClass()==s.getClass());
问题来了,当我创建一个Pair<T>
类型错误的实例时,例如:
Pair<String> s = new Pair<String>("a", 1);
编译器可以找出问题并打印此消息:</p>
pair1/PairTest1.java:12:错误:不兼容的类型:int 不能转换为 String Pair s = new Pair("a", 1);
sice<T>
被擦除为 Object 并且构造函数变为:
public Pair(Object first, Object second)
{
this.first = first;
this.second = second;
}
并且参数类型变成了对象,所以:
编译器如何确定类型错误?或类型擦除何时 发生?
解决方案
类型擦除发生在编译器生成字节码时,但编译器在验证源代码时知道泛型类型。那时还没有删除任何内容。
然而,编译器知道即使在验证期间也会发生擦除。例如,如果您重载这样的方法:
void doStuff(List<Integer> intList) {}
void doStuff(List<String> stringList) {}
编译器知道两者都将void doStuff(List xxx) {}
在擦除之后,并且您不能有两个具有相同签名的方法1,因此即使类型擦除尚未发生,验证步骤也会为此生成错误消息。
1) 参数名称不是签名的一部分
推荐阅读
- javascript - Javascript 将日期转换为回历
- c# - 在 Swagger.Net UI 中,如何从“匿名”方法中删除挂锁图标?
- django - Django-webpush:您的浏览器(Firefox)不支持服务工作者
- c - bash 有没有办法在没有 $HOME 变量的情况下知道主目录
- sql-server - 使用时区偏移值将 UTC 日期时间转换为客户端的本地日期时间
- javascript - 在javascript中调用django标签的值
- ios - 我在 iPhone 应用程序中拍摄预览视频时遇到问题
- android - 在视图层次结构中以单缓冲模式创建和使用 SurfaceTexture
- c - 双向链表中的删除函数
- javascript - 猫鼬通过操纵数据表现得很奇怪