java - 为什么擦除仍然允许覆盖/实现?
问题描述
乍一看,我认为以下是有道理的:
interface Test<T> {
T getValue(T n);
}
class Impl implements Test<Integer>{
public Integer getValue(Integer n){
return n;
}
}
并且它编译正确,所以一切看起来都很好。
但是后来我在擦除的上下文中考虑了更多,在我看来,测试接口被擦除为:
interface Test {
Object getValue(Object n);
}
那么Impl如何仍然能够实现Test呢?
解决方案
javac
实际上为此创建了桥接方法:
class Impl implements Test<Integer>{
@Override public Integer getValue(Integer n){
return n;
}
}
编译为
class Impl implements Test {
public Integer getValue(Integer n) { // overrides nothing!
return n;
}
@Override @Synthetic @Bridge public Object getValue(Object n) {
return this.getValue((Integer)n);
}
}
注意:Synthetic
andBridge
不是真正的注释,但编译后的类文件确实将这些方法标记为“合成”和“桥接”。
通过使用这些桥接方法,Java 确保如果你有一个Impl
,你可以调用Impl#getValue(Integer)Integer
(如果你知道它实际上有 type Impl
),或者你可以调用“通用” Test#getValue(Object)Object
,如果你只知道它是一个Test<?>
.
推荐阅读
- rust - 借用和使用移动值
- javascript - 在 mailto 链接中使用时,换行符无法正确显示
- node.js - 在 Facebook Marketing API 中创建 AdSet 时缺少目标受众位置错误
- c++ - 使用 QProcess 启动另一个 exe 并生成路径错误的文件
- python - Python错误:将变量组合到一行
- html - 如何编写通用 django 视图,其中一个 ListView 或 DetailView 可用于多个模型
- google-chrome-devtools - 如何关闭 Chrome 开发工具中的问题横幅?
- java - SpringBoot 中的 NullPointerException - 通过邮递员插入数据时的休眠映射
- c++ - 重载的子类函数不能调用同名的父类
- javascript - 如何暂停 HTML 音频 IF div is display: none?