首页 > 解决方案 > 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
   }

不应该是“方法的定义完全相同”?

提前抱歉我缺乏接口知识

标签: javainterface

解决方案


我猜你想实现参数化类型,但实际上是在实现原始类型。

代替

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>Cs 的角度扩展,A 的签名是,

void setVals(List vals)

void setVals(List<String> vals)并且编译器没有将 ARegex视为覆盖A,而是考虑将其重载,并且由于类型擦除,这也是非法重载。(你不能foo(List)超载foo(List<String>)


推荐阅读