views:

238

answers:

2

Is there a way to get Class object from the type variable in Java generic class? Something like that:

public class Bar extends Foo<T> {
    public Class getParameterClass() {
        return T.class; // doesn't compile
    }
}

This type information is available at compile time and therefore should not be affected by type erasure, so, theoretically, there should be a way to accomplish this. Does it exist?

+4  A: 

This works:

public static class Bar extends Foo<String> {
  public Class<?> getParameterClass() {
    return (Class<?>) (((ParameterizedType)Bar.class.getGenericSuperclass()).getActualTypeArguments()[0]);
  }
}
sfussenegger
-1. It simply can't. http://java.sun.com/docs/books/tutorial/java/generics/erasure.html
Roman
@Roman It can't? Simply try it. Downvoting without actually doing so while insisting on your wrong answer is ridiculous anyway.
sfussenegger
@Roman: It simply can. Why don't you try it for yourself?
Michael Borgwardt
Roman: I suggest you actually try this. Yes, types get erased and cannot be relied on at compile time, but you can use runtime reflection to see what those types are. It comes with a few gotchas, but broadly works.
GaryF
@GaryF: It's really more the other way round: there is no information about type parameters in *instances* of generic types, but there *is* information in compile-time entities such as classes and fields.
Michael Borgwardt
Works flawlessly, thank you.
Alexander Temerev
+2  A: 

The code snippet is a bit confusing. Is T a type parameter or a class?

public static class Bar extends Foo<String> {
    public Class<?> getParameterClass() {
        return (Class<?>) (((ParameterizedType)Bar.class.getGenericSuperclass()).getActualTypeArguments()[0]);
    }
}

public static class Bar2<T> extends Foo<T> {
    public Class<?> getParameterClass() {
        return (Class<?>) (((ParameterizedType)Bar2.class.getGenericSuperclass()).getActualTypeArguments()[0]);
    }
}


public static void main(String[] args) {
    System.out.println(new Bar().getParameterClass());
    System.out.println(new Bar2<Object>().getParameterClass());
}

Actually the second println will cause an exception.

tkr