I have a generics class, Foo
. In a method of Foo
, I want to get the class instance of type T
, but I just can\'t call T.
Many poeple don't know this trick! Actually, I just found it today! It works like a dream! Just check this example out:
public static void main(String[] args) throws NoSuchMethodException {
Date d=new Date(); //Or anything you want!
printMethods(i);
}
public static <T> void printMethods(T t){
Class<T> clazz= (Class<T>) t.getClass(); // There you go!
for ( Method m : clazz.getMethods()){
System.out.println( m.getName() );
}
}
public <T> T yourMethodSignature(Class<T> type) {
// get some object and check the type match the given type
Object result = ...
if (type.isAssignableFrom(result.getClass())) {
return (T)result;
} else {
// handle the error
}
}
You can't do it because of type erasure. See also Stack Overflow question Java generics - type erasure - when and what happens.
If you are extending or implementing any class/interface that are using generics , you may get the Generic Type of parent class/interface, without modifying any existing class/interface at all.
There could be three possibilities,
Case 1 When your class is extending a class that is using Generics
public class TestGenerics {
public static void main(String[] args) {
Type type = TestMySuperGenericType.class.getGenericSuperclass();
Type[] gTypes = ((ParameterizedType)type).getActualTypeArguments();
for(Type gType : gTypes){
System.out.println("Generic type:"+gType.toString());
}
}
}
class GenericClass<T> {
public void print(T obj){};
}
class TestMySuperGenericType extends GenericClass<Integer> {
}
Case 2 When your class is implementing an interface that is using Generics
public class TestGenerics {
public static void main(String[] args) {
Type[] interfaces = TestMySuperGenericType.class.getGenericInterfaces();
for(Type type : interfaces){
Type[] gTypes = ((ParameterizedType)type).getActualTypeArguments();
for(Type gType : gTypes){
System.out.println("Generic type:"+gType.toString());
}
}
}
}
interface GenericClass<T> {
public void print(T obj);
}
class TestMySuperGenericType implements GenericClass<Integer> {
public void print(Integer obj){}
}
Case 3 When your interface is extending an interface that is using Generics
public class TestGenerics {
public static void main(String[] args) {
Type[] interfaces = TestMySuperGenericType.class.getGenericInterfaces();
for(Type type : interfaces){
Type[] gTypes = ((ParameterizedType)type).getActualTypeArguments();
for(Type gType : gTypes){
System.out.println("Generic type:"+gType.toString());
}
}
}
}
interface GenericClass<T> {
public void print(T obj);
}
interface TestMySuperGenericType extends GenericClass<Integer> {
}
I have an (ugly but effective) solution for this problem, which I used recently:
import java.lang.reflect.TypeVariable;
public static <T> Class<T> getGenericClass()
{
__<T> ins = new __<T>();
TypeVariable<?>[] cls = ins.getClass().getTypeParameters();
return (Class<T>)cls[0].getClass();
}
private final class __<T> // generic helper class which does only provide type information
{
private __()
{
}
}
It's possible:
class Foo<T> {
Class<T> clazz = (Class<T>) DAOUtil.getTypeArguments(Foo.class, this.getClass()).get(0);
}
You need two functions from hibernate-generic-dao/blob/master/dao/src/main/java/com/googlecode/genericdao/dao/DAOUtil.java.
For more explanations, see Reflecting generics.