【问题标题】:Java Method Overwrite Lists [duplicate]Java方法覆盖列表[重复]
【发布时间】:2019-12-19 02:52:45
【问题描述】:

我有以下结构

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
   }

不应该是,“方法的定义完全一样”?

在此先抱歉我缺乏接口知识

【问题讨论】:

  • 您的C 扩展了原始类型A,这将导致各种问题。您的意思是 C 改为扩展 A&lt;T&gt; 吗?
  • 换句话说:应该是public abstract class C&lt;T extends B&gt; implements A&lt;T&gt;而不是implements A
  • 你们都提到了同样的事情,而且,ofc,这是正确的方法。现在它修复了。太棒了!

标签: java interface


【解决方案1】:

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

替换

public abstract class C <T extends B> implements A

public abstract class C <T extends B> implements A<T>

这里要注意的一个有趣的观察是,函数setVals 甚至没有使用类型参数T,即使这样也存在名称冲突。因此,起初并不明显为什么会发生这种情况,以及为什么简单地扩展 A&lt;T&gt; 有效。至少对我来说不是。

答案在于here

类的超类型可能是原始类型。会员访问权限 类被视为正常,并且超类型的成员访问是 视为原始类型。在类的构造函数中,调用 super 被视为对原始类型的方法调用。

构造函数的类型(第 8.8 节)、实例方法(第 8.4 节、第 9.4 节)或 未从其继承的原始类型 C 的非静态字段(第 8.3 节) 超类或超接口是对应于的原始类型 在对应于 C 的泛型声明中擦除其类型。

C 在我们的例子中也恰好是C

所以如果不从Cs 的角度扩展A&lt;T&gt;,A 的签名是,

void setVals(List vals)

并且编译器没有将Regex 中的void setVals(List&lt;String&gt; vals) 视为覆盖 A,而是将其视为重载,这也是非法重载因为类型擦除。 (你不能用foo(List&lt;String&gt;)重载foo(List)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-08-15
    • 1970-01-01
    • 2018-06-19
    • 1970-01-01
    • 1970-01-01
    • 2020-07-07
    • 2015-08-20
    • 1970-01-01
    相关资源
    最近更新 更多