泛型:编译器似乎无法识别传递给参数的类型与返回的类型相同 - 为什么?

mat*_*t b 1 java generics type-bounds

假设我有几个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);
}
Run Code Online (Sandbox Code Playgroud)

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

private <T extends BaseObject> GenericDao<T> getDao(Class<T> clazz) { ... }
Run Code Online (Sandbox Code Playgroud)

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

GenericDao<? extends BaseContractObject>
Run Code Online (Sandbox Code Playgroud)

而不是认识到这getDao(Class<T>)将使我返回GenericDao相同的类型T.

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

如果我改为定义getDao签名

private <T extends BaseContractObject> GenericDao<T> getDao(T obj) { ... }
Run Code Online (Sandbox Code Playgroud)

然后在编译create()看起来像的实现时没有问题

public <T extends BaseContractObject> long create(T object) {
    return getDao(object).save(object);
}
Run Code Online (Sandbox Code Playgroud)

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

eri*_*son 5

object.getClass()对象是类型的表达式T extends BaseObject返回a Class<? extends BaseObject>,而不是Class<T>正如人们所期望的那样.因此,getDao()返回它收到的相同类型的DAO; 它只是没有收到预期的类型.