我在抽象父类中有一个通用方法,要在具体子代中重写:

家长班:

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


儿童班:

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类继承自AbstractParentDataModel:

public class ConcreteDataModel extends AbstractParentDataModel {...}


这是我调用save方法的方式:

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


所以我的问题是:

为什么:


第一种方法不能编译吗?
是在第二个方法中调用父方法而不是子方法,如何解决?

最佳答案

鉴于您给我们提供的信息,调用父方法是不可能的。您输入了方法名(save),或者您的调用代码在这里有问题。

请注意,在VM级别上,泛型不存在。两种方法都具有完全相同的JVM签名:save(Ljava/util/Collection;)V-即使泛型不受欢迎,就VM而言,也是相同的方法,因此,子类中的save会覆盖来自父母

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

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


无法编译,但这:

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


做。 (原因:您可以在x.add(new ConcreteDataModel());上调用List<ConcreteDataModel>,将一些不是SubTypeOfConcreteDataModel的内容放到SubTypeOfConcreteDataModel列表中。请注意,除非您通过,否则根本无法在.add()上调用List<? extends WhateverYouWantToWriteHere>实际上是null

10-07 19:33