java - Java 方法覆盖列表
问题描述
我有以下结构
public interface A <T extends B> {
List<String> getVals();
void setVals(List<String> vals);
T getContext();
void setContext(T context);
}
public abstract class C <T extends B> implements A {
protected T context;
//Some code
}
public class Regex <T extends B> extends C <T> {
public List<String> getVals() {
//Some code
}
public void setVals(List<String> vals) {
//Some code
}
}
问题是,当我编译时,我收到以下错误:
Regex.java:[53,15]
name clash: setVals(java.util.List<java.lang.String>) in Regex and setVals(java.util.List<java.lang.String>) in A have the same erasure, yet neither overrides the other
为什么是这样?如果我要求 Intellij 为我“进行覆盖”,它会用 setVals(List vals) 替换 setVals(List vals) 。
public void setVals(List vals) {
//Some code
}
不应该是“方法的定义完全相同”?
提前抱歉我缺乏接口知识
解决方案
我猜你想实现参数化类型,但实际上是在实现原始类型。
代替
public abstract class C <T extends B> implements A
和
public abstract class C <T extends B> implements A<T>
这里要注意的一个有趣的观察是,该函数setVals
甚至没有使用类型参数T
,即使这样也存在名称冲突。因此,起初并不清楚为什么会发生这种情况,以及为什么简单地扩展A<T>
有效。至少对我来说不是。
答案就在这里,
类的超类型可以是原始类型。类的成员访问被视为正常,超类型的成员访问被视为原始类型。在类的构造函数中,对 super 的调用被视为对原始类型的方法调用。
和
未从其超类或超接口继承的原始类型 C 的构造函数(第 8.8 节)、实例方法(第 8.4 节、第 9.4 节)或非静态字段(第 8.3 节)的类型是对应于的原始类型在对应于 C 的泛型声明中擦除其类型。
C
在我们的情况下也很巧合C
。
因此,如果不A<T>
从C
s 的角度扩展,A 的签名是,
void setVals(List vals)
void setVals(List<String> vals)
并且编译器没有将 ARegex
视为覆盖A,而是考虑将其重载,并且由于类型擦除,这也是非法重载。(你不能foo(List)
超载foo(List<String>)
推荐阅读
- java - Intellij:在方法开始时移动变量
- database - 加载资源失败:服务器响应状态为 404 (Not Found) angular4 typescript
- javascript - 我想知道如何从所选文件的路径中使用相同的路径下载 XML
- multithreading - 使用互斥锁和条件变量进行线程同步
- python - 为什么使用 Socket IO 而不仅仅是 Socket?
- uwp - 运行 win 10 IOT 的树莓派与 arduino 之间如何通信?
- hibernate - Hibernate 和 MariaDB 仅将时间戳存储到秒精度?
- c++ - 如何初始化 const std::vector
- vba - Excel VBA:单击两个按钮(形状)在电子表格打开时运行两个单独的 VBA 脚本
- java - 如何从其他类获取对节点的引用?