使用类型参数覆盖通用方法时发生编译错误

时间:2019-06-08 17:36:16

标签: java generics overriding

我知道类型擦除,但这对我来说没有意义。

class Base{
   public <T> Collection<T> transform(Collection<T> list)
   { 
      return new ArrayList<T>(); 
   }
} 

public class Derived extends Base {
    @Override // compilation error
    public Collection<CharSequence> transform(Collection<CharSequence> list) {
        return new HashSet<CharSequence>();
    }
}

我的IDE中生成了一个错误:

  

“派生”中的“ transform(Collection)”与   'Base'中的'transform(Collection)';两种方法的擦除相同   却没有一个取代另一个

我的想法是我们可以覆盖transform而不会出现编译器错误。 为什么transform中的Derived没有正确覆盖Base中的方法transform?我知道这与类型擦除有关。我不明白为什么。

2 个答案:

答案 0 :(得分:5)

该方法在基类中的签名:

<T> Collection<T> transform(Collection<T> list)

说:“我将接受具有 any 类型元素的集合,并向您返回相同类型的元素集合。

根据Liskov替换原理,实现此方法的任何子类都必须执行相同的操作。特别是,它必须接受具有任何类型元素的集合。

如果您尝试使用方法来覆盖它:

Collection<CharSequence> transform(Collection<CharSequence> list)

然后,它不执行所需的操作:它不接受任何类型的集合元素,仅接受特定类型的元素。因此,它不会覆盖超类方法

通常,在子类中定义不覆盖超类中的方法的方法没有问题:您可以在子类中定义超类中不存在的新方法。但是由于类型擦除,您无法继续使用这两种方法,因为它们具有相同的签名。因此,编译器不允许您这样做。

答案 1 :(得分:4)

BaseDerived不是通用类,Collection<T>中的BaseCollection<CharSequence>中的Derived没有关系-没有关系它们之间的连接-因此出错!

您可以按以下步骤修复它:

class Base<T> {
    public Collection<T> transform(Collection<T> list) {
        return new ArrayList<>();
    }
}

class Derived extends Base<CharSequence> {
    @Override
    public Collection<CharSequence> transform(Collection<CharSequence> list) {
        return new HashSet<>();
    }
}

否则,有效替代将是:

class Derived extends Base {
    @Override
    public <T> Collection<T> transform(Collection<T> list) {
        return new HashSet<>();
    }
}