泛型接口方法签名“不正确”

时间:2013-12-07 00:17:11

标签: java generics inheritance

我很难想到这个标题,所以请原谅我。

我有一个使用以下方法的界面:

public interface Algorithm<E,F> {
    public Set<? extends Algorithm<E,F>> map(int numPartitions);
    public F reduce(Set<? extends Algorithm<E,F>> partitions);
}

以及使用以下方法实现Algorithm的类:

public class LinearSearch<T> implements Algorithm<List<T>, Integer> {
    @Override
    public Set<LinearSearch<T>> map(int numPartitions) {
        return null;
    }

    @Override
    public Integer reduce(Set<LinearSearch<T>> partitions) {
        return null;
    }
}

现在奇怪的是Eclipse正在抱怨第二种方法reduce

  

The method reduce(Set<LinearSearch<T>>) of type LinearSearch<T> must override or implement a supertype method.

尽管map方法很好,但这是事实。那么我哪里出错?

2 个答案:

答案 0 :(得分:10)

覆盖方法和参数类型

reduce方法上,参数必须为Set<? extends Algorithm<List<T>,Integer>>。它必须包含Set<? extends Algorithm<List<T>,Integer>>,而不仅仅是Set<LinearSearch<T>>。覆盖方法时,不能缩小参数类型。

JLS, Section 8.4.8.1详述了重写方法的签名:

  

在类C中声明的实例方法m1将覆盖在类A中声明的另一个实例方法m2,如果以下所有条件都为真:

     

C是A的子类。

     

m1的签名是m2签名的子签名(§8.4.2)。

     

或者:

     

m2在与C或

相同的包中具有默认访问权限是公共的,受保护的或声明的      

m1会覆盖方法m3(m3与m1不同,m3与m2不同),这样m3会覆盖m2。

这里,“subsignature”是指在类型擦除后匹配的参数类型。

覆盖方法和返回类型

但为什么map方法有效呢?因为Java允许开发人员缩小子类的重写方法的返回类型。

另一个section of the JLS, 8.4.5,涵盖了覆盖方法中的返回类型:

  

如果返回类型是引用类型,则返回类型可能会因覆盖彼此的方法而异。 return-type-substitutability的概念支持协变返回,即返回类型到子类型的特化。

     

当且仅当满足以下条件时,具有返回类型R1的方法声明d1是具有返回类型R2的另一个方法d2的return-type-substitutable:

     

如果R1无效,则R2无效。

     

如果R1是基本类型,则R2与R1相同。

     

如果R1是参考类型,则:

     

R1可以是R2的子类型,也可以通过未经检查的转换(第5.1.9节)将R1转换为R2的子类型,或

     

R1 = | R2 |

(强调我的)

答案 1 :(得分:2)

您的方法标题应如下

public Integer reduce(Set<? extends Algorithm<List<T>, Integer>> partitions)

要覆盖方法,必须使用完全相同的参数类型。如果不是,则不认为是相同的方法。

请注意,类型<E,F>是该标头的参数化部分,因此Java为您提供了一些自由,并允许您使用类定义中指定的类型。