Type arguments don't get to the runtime, so the calling code must pass a token to construct the Class<T> object at runtime. I name it token because there are many different objects you can pass to rebuild a Class<T> object at runtime, for example:
- a
String, to be used with Class.forName(name)
- a
Class<T> object
- a type token, ie a subclass of a parameterized type whose arguments are neither type variables nor wildcard (bounded or not), for example a
new List<String>(){} (I used new and the curly braces to underline that this expression returns an instance of an anonymous subclass)
With type tokens:
public class MyGenericDAO<T> {
@SuppressWarnings("unchecked")
public Class<T> getTypeParameter() throws Exception {
Type type = ((ParameterizedType) getClass().getGenericSuperclass())
.getActualTypeArguments()[0];
return (Class<T>) type;
}
}
Note that there is an unchecked conversion when you cast the Type to a Class<T>. The calling code then looks like:
MyGenericDAO<Foo> dao = new MyGenericDAO<Foo>(){};
// Then if you want an instance
Foo foo = dao.getTypeParameter().newInstance();
Again, note the curly braces, since super type tokens only work when there is a real class generated at compile time. This approach only works if the client code honors the contract and uses an anonymous inner class every time a DAO object is needed (otherwise the magic of getTypeParameter() vanishes)