【问题标题】:Generics method overriding 8泛型方法覆盖 8
【发布时间】:2013-08-12 11:49:31
【问题描述】:

为什么void say(List< ? extends Number> list) 不能被void say(List< Number> list) 覆盖。

尝试编译时会发生名称冲突。

【问题讨论】:

  • 使用哪种编程语言?

标签: java generic-programming


【解决方案1】:

您不能覆盖声明为

的方法
void say(List<? extends Number> list)   // A

void say(List<Number> list)             // B

仅仅是因为类型不等价。例如,List&lt;Integer&gt; 匹配 List&lt;? extends Number&gt; 但不匹配 List&lt;Number&gt;,所以

List<Integer> integers = Arrays.<Integer>asList(1, 2, 3);
a.say(integers);  // is valid assuming signature A
b.say(integers);  // does not compile

(有关generics, wildcards, and type relationships 的详细信息,请参阅此问题)。如果编译器确实允许您覆盖您想要的方式,那么以下是可能的:

class A {
    void say(List<? extends Number> numbers) { }
}

class B extends A {
    void say(List<Number> numbers) { numbers.add(Double.valueOf(1.0)); }
}


List<Integer> onlyIntsPlease = new ArrayList<Integer>();
B b = new B();

// Oops! The list of `Integer` will now contain a `Double`...
b.say(onlyIntsPlease);

【讨论】:

    【解决方案2】:

    这在一般理论基础和 Java 泛型的特殊性上都是不可能的。

    一般原则是覆盖方法必须可替换基类方法。例如,子类方法可以使用 wider 访问修饰符,但不能使用 narrower 访问修饰符。在你的情况下,

    void say(List<Number> list)
    

    更具约束力
    void say(List<? extends Number> list) 
    

    所以这显然违反了可替代性原则。

    一个实际的障碍是:重写是关于 runtime 多态性,而泛型是关于 compile-time 多态性,并且实例的类型参数甚至对方法分派机制。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-04
      • 1970-01-01
      • 2020-03-14
      相关资源
      最近更新 更多