在 Java 泛型中覆盖

Overriding in Java Generics

我有一个抽象的通用方法 parent class 我想在具体的 child:

中覆盖它

Parent class:

public abstract class AbstractParentDataAccess<S extends AbstractParentDataModel> 
{
   ...
  public void save(Collection<? extends S> collection) {...}
   ...
}

Child Class:

public class ConcreteDataAccess extends AbstractParentDataAccess<ConcreteDataModel> 
{
   ...
   // this does not compile
   @Override
   public void save(Collection<ConcreteDataModel> collection) {...}

   // this compiles but never gets called, the parent method is being called instead
   @Override
   public void save(Collection<? extends ConcreteDataModel> collection) {...}
   ...

}

ConcreteDataModel class 继承自 AbstractParentDataModel:

public class ConcreteDataModel extends AbstractParentDataModel {...} 

下面是我如何调用保存方法:

...
@Autowired
private ConcreteDataAccess concreteDataAccess;
....
List<ConcreteDataModel> dataList = DataService.getDataList();
concreteDataAccess.save(dataList);
...

所以我的问题是:

为什么:

  1. 第一种方法编译不通过吗?
  2. 第二个调用的是 parent 方法而不是 child 方法吗?如何解决?

根据您提供给我们的信息,不可能 正在调用 parent 方法。您打错了方法名称 (save),或者您的调用代码在这里有问题。

请注意,在 VM 级别,不存在泛型;这两种方法都具有完全相同的 JVM 签名:save(Ljava/util/Collection;)V - 即使泛型非常不正常,但就 VM 而言,它是相同的方法,因此,save 在你的 child class 覆盖 parent.

中的那个

List<ConcreteDataModel> 不会在这里编译,因为 Collection<? extends S>List<ConcreteDataModel> 允许更多类型。例如,这个:

List<ConcreteDataModel> x = new ArrayList<SubTypeOfConcreteDataModel>();

不编译,但是这个:

List<? extends ConcreteDataModel> x = new ArrayList<SubTypeOfConcreteDataModel>();

确实如此。 (原因:您可以在 List<ConcreteDataModel> 上调用 x.add(new ConcreteDataModel());,在您的 SubTypeOfConcreteDataModel 列表中放置一些不是 SubTypeOfConcreteDataModel 的内容。请注意,您不能在 [=21] 上调用 .add() =],除非你按字面意思传递 null.