9

I have a parameterized class :

class ParameterizedClass<T extends AbstractSomething> {
}

calling:

new ParameterizedClass<Something>();

So how can I get actual type Something of T by using Java Generics?

Tyler
  • 19,113
  • 19
  • 94
  • 151
TanerDiler
  • 187
  • 2
  • 8

4 Answers4

11

It can be done, but type erasure can make it very hard. As the other answers discuss, you either have to make a subclass of ParameterizedClass or add a field of type T to ParameterizedClass, and the reflection code you need to do it is convoluted.

What I recommend in these circumstances, is to work around the issue like this:

class ParameterizedClass<T> {
    private Class<T> type;

    /** Factory method */
    public static <T> ParameterizedClass<T> of(Class<T> type) {
        return new ParameterizedClass<T>(type);
    }

    /** Private constructor; use the factory method instead */
    private ParameterizedClass(Class<T> type) {
        this.type = type;
    }

    // Do something useful with type
}

Due to Java's type inference for static methods, you can construct your class without too much extra boilerplate:

ParameterizedClass<Something> foo = ParameterizedClass.of(Something.class);

That way, your ParameterizedClass is fully generic and type-safe, and you still have access to the class object.

EDIT: Addressed the comment

jqno
  • 15,133
  • 7
  • 57
  • 84
  • It ***IS*** possible. This answer is wrong. Check the other answer which has the solution. – Adam Arold Apr 07 '17 at 19:46
  • @AdamArold I didn't know it yet at the time I wrote the answer, but you're right. I still don't recommend it, though. I've updated my answer accordingly. – jqno Apr 13 '17 at 06:40
8

You could use this trick in your constructor: (see http://www.hibernate.org/328.html)

Class<T> parameterType = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];

But I believe this code only works when the class is sub-classed and an instance of the sub-class executes it.

Adrian Pronk
  • 13,486
  • 7
  • 36
  • 60
  • I know this trick and am using on DAO classes. But this is not what I'm looking. To use this trick, I guess, we have to define actual value of generic type of parent class on sourcecode. GenericDAO UserDAO extends GenericDAO – TanerDiler Aug 19 '10 at 08:59
3

If you mean just from the object itself, you can't. Type erasure means that information is lost.

If you have a field which uses the parameterized type with a concrete type argument though, that information is preserved.

See Angelika Langer's Generics FAQ, and particularly the section on type erasure.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
0

This is a mostly problematic topic, since it only works under certain conditions like expected (expecially in complex scenarios).

But Xebia published a good article on the whole thing.

Johannes Wachter
  • 2,715
  • 17
  • 17