gpt4 book ai didi

java - 泛型和 Java : how does "extends" work?

转载 作者:行者123 更新时间:2023-11-30 05:14:13 24 4
gpt4 key购买 nike

我正在尝试为我的应用程序编写通用数据访问层。我有多个 Hibernate 实体,它们大部分相同,并且在 Java 中表示为类层次结构(它们在 Hibernate 中没有作为层次结构实现):

public abstract class Entity1 {
// some implementation
}
public class Entity2 extends Entity1 {
// some implementation
}
public class Entity3 extends Entity1 {
// some implementation
}

这些实体的 DAO 大多相同(方法的类型签名和要求 Hibernate 的类除外)。我希望能够编写一个像这样的通用 DAO:

public interface EntityDao<T extends Entity1> {
List<T>getEntities();
void saveOrUpdateEntity(T entity);
}

public class EntityDaoImpl implements EntityDao<Entity1> {
private final HibernateTemplate hibernateTemplate;

private final Class<DBEnumerationDto> clazz;

public DBEnumerationDaoHibernateImpl(SessionFactory sessionFactory, Class<DBEnumerationDto> clazz) {
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
this.clazz = clazz;
}

@Override
public List<Entity1> getEntities() {
return this.hibernateTemplate.loadAll(this.clazz);
}
@Override
public void saveOrUpdateEntity(Entity1 entity) {
this.hibernateTemplate.saveOrUpdate(entity);
}
}

到目前为止,一切都很好。但是使用这个时出现问题:

Entity1 test = new Entity1();
Entity1Dao<? extends Entity1> dao = ...; // get the dao forthe current operation
dao.saveOrUpdate(test);

这会产生编译器错误:The method saveOrUpdateEntity(capture#5-of ? extends Entity1) in the type EntityDao<capture#5-of ? extends Entity1> is not applicable for the arguments (Entity1)

我猜这个问题与 Java Generics: casting to ? (or a way to use an arbitrary Foo<?>) 有关但我无法真正掌握以哪种方式。

我应该如何修复我的代码?还是我的方法不对?

最佳答案

想一想失败示例第二行中的问号(通配符)的含义。

您已获得Entity1Dao ,具有未知的泛型参数(唯一知道的是该参数是 Entity1 的子类)。因此,按如下方式实际实现是完全合法的:

Entity1Dao<? extends Entity1> dao = getEntityDao();

private Entity1Dao<Entity2> getEntityDao()
{
return new Entity1Dao<Entity2>(); // Or whatever (the construction itself is irrelevant)
}

由于通配符,分配 Entity1Dao<Entity2>是完全合法的。现在您转到下一行并尝试调用 dao.saveOrUpdate() ,传入 Entity1 类型的对象.

这不起作用 - 正如我们上面刚刚所示,dao 在 Entity2 上参数化。所以只有具体方法saveOrUpdate(Entity2 entity) !这就是为什么编译器会向您发出类型警告。

<小时/>

总之,您的问题是“extends”关键字,它允许通配符参数成为您实际类型的子类,因此无法处理它。如果您将通配符更改为使用 super (即 <? super Entity1> ),则这将进行编译,因为编译器可以确保无论实际的泛型类型如何, saveOrUpdate 都会被编译。方法将接受 Entity1 类型的参数。

通常情况下,与某些确切类型相比,您需要将相同的参数同时作为 superextends ,这意味着您根本不能使用通配符。在这种情况下,您可能希望在类的具体类型上泛化整个方法,如下所示:

public <T extends Entity1> void saveEntityExample(T test)
{
Entity1Dao<T> dao = getEntityDao();
dao.saveOrUpdate(test);
}

private <T extends Entity1> Entity1Dao<T> getEntityDao()
{
// Get the DAO however
}
<小时/>

您可能还想查看 this answer 中链接的 Josh Bloch 的演讲。 ,特别是了解“PECS”的概念。与“扩展”总是答案的类不同,当涉及到泛型时,需要考虑它们是否意味着“扩展”或“ super ”,而助记符是记住一般规则的一种有用方法。

关于java - 泛型和 Java : how does "extends" work?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2229050/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com