在 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);
...
所以我的问题是:
为什么:
- 第一种方法编译不通过吗?
- 第二个调用的是 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
.
我有一个抽象的通用方法 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);
...
所以我的问题是:
为什么:
- 第一种方法编译不通过吗?
- 第二个调用的是 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
.