Let's say I have several POJOs which all extend a common supertype, BaseObject
.
I have a GenericDao
which is declared as public interface GenericDao<T>
.
For each type-specific DAO, I have an interface which extends the generic type and restricts it to a concrete type (public interface UserDao extends GenericDao<User>
) and then an implementation of the type-specific DAO.
In a class that attempts to use a number of GenericDao
implementations, I have a method that looks like
public <T extends BaseObject> long create(T object) {
return getDao(object.getClass()).save(object);
}
If I implement getDao()
so that it's parameter is a Class
object, such as
private <T extends BaseObject> GenericDao<T> getDao(Class<T> clazz) { ... }
Then the call to getDao(object.getClass()
in the create()
method fails to compile - the compiler appears to interpret the return type of getDao()
as
GenericDao<? extends BaseContractObject>
rather than recognizing that getDao(Class<T>)
is going to return me a GenericDao
of the same type T
.
Can someone explain why this is? I understand that repeated appearances of the same type bound or wildcard don't necessary refer to the same type; however it seems like the compiler should recognize from the signature of getDao(Class<T>)
that the T passed in should be the same T returned (but obviously it isn't capable of recognizing this, the why is the part I fail to grasp).
If I instead define getDao
's signature to be
private <T extends BaseContractObject> GenericDao<T> getDao(T obj) { ... }
Then there is no issue in compiling a create()
implementation which looks like
public <T extends BaseContractObject> long create(T object) {
return getDao(object).save(object);
}
So why is the compiler capable of recognizing in this case that the T
argument passed to getDao(T)
is the same T
in the return type, whereas it couldn't recognize this when the argument was Class<T>
?