1

假设我有几个 POJO,它们都扩展了一个共同的超类型,BaseObject.

我有一个GenericDao声明为public interface GenericDao<T>.

对于每个特定类型的 DAO,我都有一个接口,它扩展了泛型类型并将其限制为具体类型 ( public interface UserDao extends GenericDao<User>),然后是特定类型 DAO 的实现。

在一个尝试使用多种GenericDao实现的类中,我有一个看起来像的方法

public <T extends BaseObject> long create(T object) {
    return getDao(object.getClass()).save(object);
}

如果我实现getDao()它的参数是一个Class对象,例如

private <T extends BaseObject> GenericDao<T> getDao(Class<T> clazz) { ... }

getDao(object.getClass()然后方法中的调用create()无法编译 - 编译器似乎将返回类型解释getDao()

GenericDao<? extends BaseContractObject>

而不是认识到这getDao(Class<T>)会返回给我一个GenericDao相同的类型T

有人可以解释这是为什么吗?我了解重复出现的相同类型绑定或通配符不一定指相同类型;然而,编译器似乎应该从签名中识别出getDao(Class<T>)传入的 T 应该与返回的 T 相同(但显然它无法识别这一点,为什么是我无法掌握的部分)。

如果我改为将getDao的签名定义为

private <T extends BaseContractObject> GenericDao<T> getDao(T obj) { ... }

create()那么编译一个看起来像的实现就没有问题了

public <T extends BaseContractObject> long create(T object) {
    return getDao(object).save(object);
}

那么为什么编译器能够在这种情况下识别T传递给的参数在返回类型中getDao(T)是相同T的,而当参数是时它无法识别Class<T>呢?

4

3 回答 3

5

表达式object.getClass(),其中 object 是 type T extends BaseObject,返回 a Class<? extends BaseObject>,而不是Class<T>预期的 a 。因此,getDao()返回的是它接收到的相同类型的 DAO;它只是没有收到预期的类型。

于 2010-06-25T18:47:22.893 回答
2

这是一个经典的类型擦除问题。 getClass()具有以下签名:

public final native Class<? extends Object> getClass();

如果你有 aStringgetClass()在上面做 a ,你得到的课程是Class<? extends String>. javadocs阅读:

 * @return The <code>java.lang.Class</code> object that represents
 *         the runtime class of the object.  The result is of type
 *         {@code Class<? extends X>} where X is the
 *         erasure of the static type of the expression on which
 *         <code>getClass</code> is called.

您需要强制执行以下强制转换才能使其工作:

@SuppressWarnings("unchecked")
Class<T> clazz = (Class<T>)object.getClass();
return getDao(clazz).save(object);

这对我行得通。

于 2010-06-25T18:50:26.653 回答
0

我认为这应该可以解释为什么约束没有达到您的预期:

http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeParameters.html#FAQ206

于 2010-06-25T18:44:02.003 回答