仿制药:编译器似乎无法认识到传递给参数的类型与返回的类型相同 - 为什么?
-
30-09-2019 - |
题
假设我有几个pojos,都扩展了一个普通的超级构想, 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>
?
解决方案
表达方式 object.getClass()
, ,对象是类型的 T extends BaseObject
, ,返回a Class<? extends BaseObject>
, ,不是 Class<T>
正如人们可能期望的那样。所以, getDao()
正在返回与收到相同类型的DAO;只是没有收到预期类型。
其他提示
这是一个经典的擦除问题。 getClass()
具有以下签名:
public final native Class<? extends Object> getClass();
如果你有 String
并做一个 getClass()
在上面,你得到的课是 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);
这对我行得通。
我认为这应该解释为什么约束没有做您期望的事情:
http://www.angelikalanger.com/genericsfaq/faqsections/typeparameters.html#faq206