By Glenn


2010-08-04 08:44:44 8 Comments

How can I achieve this?

public class GenericClass<T>
{
    public Type getMyType()
    {
        //How do I return the type of T?
    }
}

Everything I have tried so far always returns type Object rather than the specific type used.

25 comments

@PetermaxX 2019-12-06 01:53:49

Here is my solution. The examples should explain it. The only requirement is that a subclass must set the generic type, not an object.

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.HashMap;
import java.util.Map;

public class TypeUtils {

    /*** EXAMPLES ***/

    public static class Class1<A, B, C> {

        public A someA;
        public B someB;
        public C someC;

        public Class<?> getAType() {
            return getTypeParameterType(this.getClass(), Class1.class, 0);
        }

        public Class<?> getCType() {
            return getTypeParameterType(this.getClass(), Class1.class, 2);
        }
    }

    public static class Class2<D, A, B, E, C> extends Class1<A, B, C> {

        public B someB;
        public D someD;
        public E someE;
    }

    public static class Class3<E, C> extends Class2<String, Integer, Double, E, C> {

        public E someE;
    }

    public static class Class4 extends Class3<Boolean, Long> {

    }

    public static void test() throws NoSuchFieldException {

        Class4 class4 = new Class4();
        Class<?> typeA = class4.getAType(); // typeA = Integer
        Class<?> typeC = class4.getCType(); // typeC = Long

        Field fieldSomeA = class4.getClass().getField("someA");
        Class<?> typeSomeA = TypeUtils.getFieldType(class4.getClass(), fieldSomeA); // typeSomeA = Integer

        Field fieldSomeE = class4.getClass().getField("someE");
        Class<?> typeSomeE = TypeUtils.getFieldType(class4.getClass(), fieldSomeE); // typeSomeE = Boolean


    }

    /*** UTILS ***/

    public static Class<?> getTypeVariableType(Class<?> subClass, TypeVariable<?> typeVariable) {
        Map<TypeVariable<?>, Type> subMap = new HashMap<>();
        Class<?> superClass;
        while ((superClass = subClass.getSuperclass()) != null) {

            Map<TypeVariable<?>, Type> superMap = new HashMap<>();
            Type superGeneric = subClass.getGenericSuperclass();
            if (superGeneric instanceof ParameterizedType) {

                TypeVariable<?>[] typeParams = superClass.getTypeParameters();
                Type[] actualTypeArgs = ((ParameterizedType) superGeneric).getActualTypeArguments();

                for (int i = 0; i < typeParams.length; i++) {
                    Type actualType = actualTypeArgs[i];
                    if (actualType instanceof TypeVariable) {
                        actualType = subMap.get(actualType);
                    }
                    if (typeVariable == typeParams[i]) return (Class<?>) actualType;
                    superMap.put(typeParams[i], actualType);
                }
            }
            subClass = superClass;
            subMap = superMap;
        }
        return null;
    }

    public static Class<?> getTypeParameterType(Class<?> subClass, Class<?> superClass, int typeParameterIndex) {
        return TypeUtils.getTypeVariableType(subClass, superClass.getTypeParameters()[typeParameterIndex]);
    }

    public static Class<?> getFieldType(Class<?> clazz, AccessibleObject element) {
        Class<?> type = null;
        Type genericType = null;

        if (element instanceof Field) {
            type = ((Field) element).getType();
            genericType = ((Field) element).getGenericType();
        } else if (element instanceof Method) {
            type = ((Method) element).getReturnType();
            genericType = ((Method) element).getGenericReturnType();
        }

        if (genericType instanceof TypeVariable) {
            Class<?> typeVariableType = TypeUtils.getTypeVariableType(clazz, (TypeVariable) genericType);
            if (typeVariableType != null) {
                type = typeVariableType;
            }
        }

        return type;
    }

}

@Bonestack 2019-10-28 22:35:10

I did the same as @Moesio Above but in Kotlin it could be done this way:

class A<T : SomeClass>() {

    var someClassType : T

    init(){
    this.someClassType = (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class<T>
    }

}

@ewernli 2010-08-04 08:52:31

Generics are not reified at run-time. This means the information is not present at run-time.

Adding generics to Java while mantaining backward compatibility was a tour-de-force (you can see the seminal paper about it: Making the future safe for the past: adding genericity to the Java programming language).

There is a rich literature on the subject, and some people are dissatisfied with the current state, some says that actually it's a lure and there is no real need for it. You can read both links, I found them quite interesting.

@Pacerier 2012-03-06 12:35:07

Of course we are dissatisfied, .NET has much better generic handling mechanism

@Joachim Sauer 2012-07-19 14:34:07

@Pacerier: but reified generics alone would not bring Java to the level of .NET. Value types an specialized code for those is at least equally important for why .NET is better in the generics area.

@Pacerier 2012-07-19 17:31:02

@JoachimSauer, yes value types. I'd always wanted those in java. Btw what do you mean by specialized code?

@Joachim Sauer 2012-07-19 18:45:58

@Pacerier: well, in Java an array of non-primitives is always "one-reference-per-element" large. With specialized code for value types that could be "x-bytes-per-element" where x is the size of the value type. I.e. you could use real packed arrays as used in C/C++.

@Pacerier 2012-07-19 19:30:40

@JoachimSauer, lol I'd thought you said "value types" and "specialized code" as if they were two different things.

@Joachim Sauer 2012-07-21 09:41:44

@Pacerier: well, there could be a naive implementation of value types as "the same as reference types, except they can be freely copied". From a functional perspective that would have the same effect, but only with specialized code do you get the real benefits of value types.

@spaaarky21 2014-04-24 19:02:49

Doesn't FrVaBe's answer imply that the generic type IS present at runtime? It seems that Java simply doesn't provide a convenient mechanism for accessing it.

@ewernli 2014-04-25 12:53:06

@spaaarky21 No, generic type parameters are removed during compilation (so-called "erasure", you can google it). The trick in FrVaBe's answer works only if the type params of the superclass are known statically (see the first commment by Johnathn)

@Abhijit Sarkar 2018-10-26 22:30:51

Java type erasure is a historical design flaw; more code has been written to get around it than was written to implement it.

@M.kazem Akhgary 2018-11-25 19:03:51

people who say there is no real need for it are not real programmers.

@Ali Yeganeh 2017-02-15 16:55:04

public abstract class AbstractDao<T>
{
    private final Class<T> persistentClass;

    public AbstractDao()
    {
        this.persistentClass = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass())
                .getActualTypeArguments()[0];
    }
}

@KMC 2019-05-22 13:45:56

I'm upvoting this answer because it's a solution that works for the question being asked. However, for those who wants to navigate upward in class hierarchy like myself with more than one Generic class, this won't work. Because you will get java.lang.object instead of actual class.

@BabaNew 2019-08-13 08:30:41

Please note that this solution works ONLY if the class that holds the generic type is ABSTRACT

@JRA_TLL 2019-09-26 13:36:26

Did not work with my abstract class in Java 11

@Googie 2020-01-02 17:20:12

@JRA_TLL you apparently did something wrong. I just used it with Java 12 and works like a charm.

@Cody A. Ray 2013-11-04 19:55:04

Use Guava.

import com.google.common.reflect.TypeToken;
import java.lang.reflect.Type;

public abstract class GenericClass<T> {
  private final TypeToken<T> typeToken = new TypeToken<T>(getClass()) { };
  private final Type type = typeToken.getType(); // or getRawType() to return Class<? super T>

  public Type getType() {
    return type;
  }

  public static void main(String[] args) {
    GenericClass<String> example = new GenericClass<String>() { };
    System.out.println(example.getType()); // => class java.lang.String
  }
}

A while back, I posted some full-fledge examples including abstract classes and subclasses here.

Note: this requires that you instantiate a subclass of GenericClass so it can bind the type parameter correctly. Otherwise it'll just return the type as T.

@Saro Taşciyan 2014-02-03 08:27:31

The constructor TypeToken(Type) is not visible

@Cody A. Ray 2014-02-04 00:15:09

Notice that I create an empty anonymous subclass (see the two curly braces at the end). This uses reflection to battle Java's runtime type erasure. You can learn more here: code.google.com/p/guava-libraries/wiki/ReflectionExplained

@Manu Manjunath 2014-11-07 06:37:48

@CodyA.Ray This approach seems to battle type erasure in the most elegant way. But in your example, you're instantiating an abstract class. Am I missing something?

@Manu Manjunath 2014-11-07 06:38:32

@CodyA.Ray I'm looking for a way to do this: CoolClass<Integer> cool = new CoolClass<Integer>();Class c = cool.getType(); // Should return Integer.class

@Cody A. Ray 2014-11-07 19:33:17

Edited. The abstract class was a copy-paste mistake from the article that I linked: codyaray.com/2013/01/finding-generic-type-parameters-with-gu‌​ava

@Manu Manjunath 2014-11-14 11:16:20

@CodyA.Ray Your code throws a java.lang.IllegalArgumentException: class com.google.common.reflect.TypeToken isn't parameterized. So I changed the line new TypeToken(getClass()) { } to new TypeToken<T>(getClass()) { }. Now, code runs fine, but Type is still 'T'. See this: gist.github.com/m-manu/9cda9d8f9d53bead2035

@Dominik 2016-03-23 10:39:50

how could you get 14 positives if your code not only is not working but also is breaking basic rules of generics in java. its perfect example of wishful thinking- if java works that way, there will not be any problems with generic parameter types instantiation.

@Cody A. Ray 2016-03-23 12:56:40

@Dominik Please see the updated example that you can copy and paste to test yourself. I've also added a note clarifying that you must instantiate a subclass (as shown). As a general etiquette advise, please read any linked articles and related javadocs before you accuse a poster of "wishful thinking". I've used similar production code multiple times. The Guava helpers I'm demonstrating are intended for this exact use case and their javadocs show almost an exact answer to this question. docs.guava-libraries.googlecode.com/git/javadoc/com/google/…

@Dominik 2016-03-23 17:57:41

yeah right, my bad. I have read quite a bit about that approach, and previous information I have found were about using parametrized superclass which I haven't realized you are doing. Another thing is that if I try to use this approach in a constructor of the GenericClass it will return T (and I am not sure why this is the case).

@Richard Sand 2017-07-10 21:11:14

This answer works great with Java8 - I have an interface and a factory class to emit various types, and wanted users to be able to easily determine the type. In my interface I added the default method: default Type getParameterType() { final TypeToken<T> typeToken = new TypeToken<T>(getClass()) {}; final Type type = typeToken.getType(); return type; }

@Martin 2018-11-21 10:40:03

@CodyA.Ray Since this only works with subclasses of GenericClass, you should make that class abstract so wrong usage doesn’t compile.

@matoni 2019-06-18 06:16:18

Note, your example with anonymous class does not require guava's TypeToken, see Yaroslav Kovbas answer. It would be nice to mention solution options e.g. with reference to have it in single place.

@Franzi 2019-11-19 14:36:31

Url to ReflectionExplained has changed that's the current url github.com/google/guava/wiki/ReflectionExplained

@TheLetch 2018-10-25 22:00:40

It might be useful to someone. You can Use java.lang.ref.WeakReference; this way:

class SomeClass<N>{
  WeakReference<N> variableToGetTypeFrom;

  N getType(){
    return variableToGetTypeFrom.get();
  }
}

@Abhijit Sarkar 2018-10-26 22:39:31

How's this class supposed to be used? Why WeakReference? Please provide some explanation with your answer, not just some code.

@TheLetch 2018-10-26 23:17:52

So if you have a SomeClass<MyClass> you can instantiate SomeClass and call getType on that instance and have the runtime to be MyClass.

@Abhijit Sarkar 2018-10-27 03:02:17

Sure, but why WeakReference? What you said is not different from most of the other answers.

@TheLetch 2018-10-28 00:51:53

First my approach is shorter(less code), second the Weak references do not prevent their referents from being made finalizable, and as far as I know it doesn't use reflection, thus it's fast

@Frontear 2019-09-03 05:34:54

This does not get the type of anything, this returns an object of that type, which, fyi, you can do with literally any kind of wrapper (AtomicReference, List, Set).

@kayz1 2018-09-27 08:55:07

public static final Class<?> getGenericArgument(final Class<?> clazz)
{
    return (Class<?>) ((ParameterizedType) clazz.getGenericSuperclass()).getActualTypeArguments()[0];
}

@Paul92 2018-03-08 18:56:46

One simple solution for this cab be like below

public class GenericDemo<T>{
    private T type;

    GenericDemo(T t)
    {
        this.type = t;
    }

    public String getType()
    {
        return this.type.getClass().getName();
    }

    public static void main(String[] args)
    {
        GenericDemo<Integer> obj = new  GenericDemo<Integer>(5);
        System.out.println("Type: "+ obj.getType());
    }
}

@Moesio 2014-09-28 19:44:37

I used follow approach:

public class A<T> {

    protected Class<T> clazz;

    public A() {
        this.clazz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }

    public Class<T> getClazz() {
        return clazz;
    }
}

public class B extends A<C> {
   /* ... */
    public void anything() {
       // here I may use getClazz();
    }
}

@yuyang 2019-03-20 22:23:46

I got "Exception in thread "main" java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType" with this sample code

@Mark Karchner 2016-12-01 18:20:00

I found this to be a simple understandable and easily explainable solution

public class GenericClass<T> {

    private Class classForT(T...t) {
        return t.getClass().getComponentType();
    }

    public static void main(String[] args) {
        GenericClass<String> g = new GenericClass<String>();

        System.out.println(g.classForT());
        System.out.println(String.class);
    }
}

@Christopher Schneider 2017-04-18 19:46:46

Explain (T...t). (That's why this code doesn't work.)

@Lin Yu Cheng 2016-07-27 10:43:42

Here is my solution

public class GenericClass<T>
{
    private Class<T> realType;

    public GenericClass() {
        findTypeArguments(getClass());
    }

    private void findTypeArguments(Type t) {
        if (t instanceof ParameterizedType) {
            Type[] typeArgs = ((ParameterizedType) t).getActualTypeArguments();
            realType = (Class<T>) typeArgs[0];
        } else {
            Class c = (Class) t;
            findTypeArguments(c.getGenericSuperclass());
        }
    }

    public Type getMyType()
    {
        // How do I return the type of T? (your question)
        return realType;
    }
}

No matter how many level does your class hierarchy has, this solution still works, for example:

public class FirstLevelChild<T> extends GenericClass<T> {

}

public class SecondLevelChild extends FirstLevelChild<String> {

}

In this case, getMyType() = java.lang.String

@Mohy Eldeen 2016-09-08 17:38:30

This is not returning the type of T. It is returning T not java.lang.String besides the code is failing to covert Type to Class<T>

@Lin Yu Cheng 2016-10-26 00:28:29

Here is a online sample I made. Click compile and execute, then you can get the result. tutorialspoint.com/…

@Andre 2017-07-26 21:14:24

Works for me - when WildFly Weld CDI broke an alternative method.

@yuyang 2019-03-20 22:25:44

I got Exception in thread "main" java.lang.NullPointerException at Main$ClassA.findTypeArguments(Main.java:54) at Main$ClassA.findTypeArguments(Main.java:54) at Main$ClassA.findTypeArguments(Main.java:54) at Main$ClassA.<init>(Main.java:43) at Main.main(Main.java:61)

@DaBlick 2016-07-14 15:20:39

I think there is another elegant solution.

What you want to do is (safely) "pass" the type of the generic type parameter up from the concerete class to the superclass.

If you allow yourself to think of the class type as "metadata" on the class, that suggests the Java method for encoding metadata in at runtime: annotations.

First define a custom annotation along these lines:

import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface EntityAnnotation {
    Class entityClass();
}

You can then have to add the annotation to your subclass.

@EntityAnnotation(entityClass =  PassedGenericType.class)
public class Subclass<PassedGenericType> {...}

Then you can use this code to get the class type in your base class:

import org.springframework.core.annotation.AnnotationUtils;
.
.
.

private Class getGenericParameterType() {
    final Class aClass = this.getClass();
    EntityAnnotation ne = 
         AnnotationUtils.findAnnotation(aClass, EntityAnnotation.class);

    return ne.entityClass();
}

Some limitations of this approach are:

  1. You specify the generic type (PassedGenericType) in TWO places rather than one which is non-DRY.
  2. This is only possible if you can modify the concrete subclasses.

@agodinhost 2019-01-11 02:35:06

Yes, it's non-DRY, however it's cleaner than the extension approach suggested above. I liked it. thanks

@galex 2016-05-17 09:45:14

To complete some of the answers here, I had to get the ParametrizedType of MyGenericClass, no matter how high is the hierarchy, with the help of recursion:

private Class<T> getGenericTypeClass() {
        return (Class<T>) (getParametrizedType(getClass())).getActualTypeArguments()[0];
}

private static ParameterizedType getParametrizedType(Class clazz){
    if(clazz.getSuperclass().equals(MyGenericClass.class)){ // check that we are at the top of the hierarchy
        return (ParameterizedType) clazz.getGenericSuperclass();
    } else {
        return getParametrizedType(clazz.getSuperclass());
    }
}

@Dimitar 2010-08-04 08:47:08

I dont think you can, Java uses type erasure when compiling so your code is compatible with applications and libraries that were created pre-generics.

From the Oracle Docs:

Type Erasure

Generics were introduced to the Java language to provide tighter type checks at compile time and to support generic programming. To implement generics, the Java compiler applies type erasure to:

Replace all type parameters in generic types with their bounds or Object if the type parameters are unbounded. The produced bytecode, therefore, contains only ordinary classes, interfaces, and methods. Insert type casts if necessary to preserve type safety. Generate bridge methods to preserve polymorphism in extended generic types. Type erasure ensures that no new classes are created for parameterized types; consequently, generics incur no runtime overhead.

http://docs.oracle.com/javase/tutorial/java/generics/erasure.html

@Henning 2010-08-04 08:51:25

Jup, it's impossible. Java would need reified generics for that to work.

@Joeri Hendrickx 2010-08-04 09:22:51

Sure, you can.

Java does not use the information at run time, for backwards compatibility reasons. But the information is actually present as metadata and can be accessed via reflection (but it is still not used for type-checking).

From the official API:

http://download.oracle.com/javase/6/docs/api/java/lang/reflect/ParameterizedType.html#getActualTypeArguments%28%29

However, for your scenario I would not use reflection. I'm personally more inclined to use that for framework code. In your case I would just add the type as a constructor param.

@Jonathan 2011-08-19 04:38:55

getActualTypeArguments only returns the type arguments for the immediate class. If you have a complex type hierarchy where T could be parameterized anywhere in the hierarchy, you'll need to do a bit of work to figure out what it is. This is more or less what TypeTools does.

@Yaroslav Kovbas 2015-11-30 11:13:08

Here is working solution!!!

@SuppressWarnings("unchecked")
    private Class<T> getGenericTypeClass() {
        try {
            String className = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0].getTypeName();
            Class<?> clazz = Class.forName(className);
            return (Class<T>) clazz;
        } catch (Exception e) {
            throw new IllegalStateException("Class is not parametrized with generic type!!! Please use extends <> ");
        }
    } 

NOTES: Can be used only as superclass
1. Has to be extended with typed class (Child extends Generic<Integer>)
OR

2. Has to be created as anonymous implementation (new Generic<Integer>() {};)

@Henning 2010-08-04 08:55:26

As others mentioned, it's only possible via reflection in certain circumstances.

If you really need the type, this is the usual (type-safe) workaround pattern:

public class GenericClass<T> {

     private final Class<T> type;

     public GenericClass(Class<T> type) {
          this.type = type;
     }

     public Class<T> getMyType() {
         return this.type;
     }
}

@Eliseo Ocampos 2013-08-16 16:21:05

I like this answer but it's a little cumbersome to instantiate: GenericClass<AnotherClass> g = new GenericClass<AnotherClass>(AnotherClass.class);

@djmj 2014-10-16 21:55:09

Its even more verbose if you use a dao/factory/manager approach. Foo foo1 = GetDao<Foo>(Foo.class).get(Foo.class, 1)

@naXa 2014-12-10 08:11:02

@djmj, if you save Foo.class in DAO, you don't need to pass it in methods. And vice versa. Actually your example will be looking like Foo foo1 = GetDao<Foo>(Foo.class).get(1);. It's not so bad I think.

@djmj 2014-12-10 10:24:44

Thats true, but not working in all cases like stateless remote beans which are instantiated by container/reflection.

@Tomáš Zato - Reinstate Monica 2015-05-01 17:08:43

Just as a follow-up to my previous comment - after lot of pain playing with reflection, I ended up using this answer.

@Joeri Hendrickx 2016-08-01 20:04:48

You can get around the superfluous reference by providing a generic static factory method. Something like public static <T> GenericClass<T> of(Class<T> type) {...} and then call it as such: GenericClass<String> var = GenericClass.of(String.class). A bit nicer.

@Pablo Trinidad 2014-08-15 13:50:37

Just in case you use store a variable using the generic type you can easily solve this problem adding a getClassType method as follows:

public class Constant<T> {
  private T value;

  @SuppressWarnings("unchecked")
  public Class<T> getClassType () {
    return ((Class<T>) value.getClass());
  }
}

I use the provided class object later to check if it is an instance of a given class, as follows:

Constant<?> constant = ...;
if (constant.getClassType().equals(Integer.class)) {
    Constant<Integer> integerConstant = (Constant<Integer>)constant;
    Integer value = integerConstant.getValue();
    // ...
}

@Radiodef 2015-04-11 02:30:51

This is problematic, unfortunately. First of all, what if value is null? Second of all, what if value is a subclass of T? Constant<Number> c = new Constant<Number>(new Integer(0)); Class<Number> n = c.getClassType(); returns Integer.class when it should return Number.class. It would be more correct to return Class<? extends T>. Integer.class is a Class<? extends Number> but not a Class<Number>.

@HRgiger 2014-03-05 12:19:33

Here is my trick:

public class Main {

    public static void main(String[] args) throws Exception {

        System.out.println(Main.<String> getClazz());

    }

    static <T> Class getClazz(T... param) {

        return param.getClass().getComponentType();
    }

}

@Radiodef 2015-04-11 02:41:13

Note: this does not work when T is a type variable. In the case that T is a type variable, the varargs creates an array of erasure of T. See e.g. http://ideone.com/DIPNwd.

@yahya 2015-04-24 07:19:31

This returns "Object"

@PJWeisberg 2013-03-13 21:25:01

Here's one way, which I've had to use once or twice:

public abstract class GenericClass<T>{
    public abstract Class<T> getMyType();
}

Along with

public class SpecificClass extends GenericClass<String>{

    @Override
    public Class<String> getMyType(){
        return String.class;
    }
}

@ggb667 2013-11-05 15:02:30

This technically works, however it doesn't solve the general case, and I think that is what the original poster is after.

@VirtualMichael 2015-09-23 04:06:03

This doesn't deserve to be voted down like is has - the original poster hasn't been explicit. This answer offers a design pattern that does work and is easy to implement, provided it is suitable to make the generic class abstract.

@Ondrej Bozek 2013-02-21 16:59:19

Technique described in this article by Ian Robertson works for me.

In short quick and dirty example:

 public abstract class AbstractDAO<T extends EntityInterface, U extends QueryCriteria, V>
 {
    /**
     * Method returns class implementing EntityInterface which was used in class
     * extending AbstractDAO
     *
     * @return Class<T extends EntityInterface>
     */
    public Class<T> returnedClass()
    {
        return (Class<T>) getTypeArguments(AbstractDAO.class, getClass()).get(0);
    }

    /**
     * Get the underlying class for a type, or null if the type is a variable
     * type.
     *
     * @param type the type
     * @return the underlying class
     */
    public static Class<?> getClass(Type type)
    {
        if (type instanceof Class) {
            return (Class) type;
        } else if (type instanceof ParameterizedType) {
            return getClass(((ParameterizedType) type).getRawType());
        } else if (type instanceof GenericArrayType) {
            Type componentType = ((GenericArrayType) type).getGenericComponentType();
            Class<?> componentClass = getClass(componentType);
            if (componentClass != null) {
                return Array.newInstance(componentClass, 0).getClass();
            } else {
                return null;
            }
        } else {
            return null;
        }
    }

    /**
     * Get the actual type arguments a child class has used to extend a generic
     * base class.
     *
     * @param baseClass the base class
     * @param childClass the child class
     * @return a list of the raw classes for the actual type arguments.
     */
    public static <T> List<Class<?>> getTypeArguments(
            Class<T> baseClass, Class<? extends T> childClass)
    {
        Map<Type, Type> resolvedTypes = new HashMap<Type, Type>();
        Type type = childClass;
        // start walking up the inheritance hierarchy until we hit baseClass
        while (!getClass(type).equals(baseClass)) {
            if (type instanceof Class) {
                // there is no useful information for us in raw types, so just keep going.
                type = ((Class) type).getGenericSuperclass();
            } else {
                ParameterizedType parameterizedType = (ParameterizedType) type;
                Class<?> rawType = (Class) parameterizedType.getRawType();

                Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
                TypeVariable<?>[] typeParameters = rawType.getTypeParameters();
                for (int i = 0; i < actualTypeArguments.length; i++) {
                    resolvedTypes.put(typeParameters[i], actualTypeArguments[i]);
                }

                if (!rawType.equals(baseClass)) {
                    type = rawType.getGenericSuperclass();
                }
            }
        }

        // finally, for each actual type argument provided to baseClass, determine (if possible)
        // the raw class for that type argument.
        Type[] actualTypeArguments;
        if (type instanceof Class) {
            actualTypeArguments = ((Class) type).getTypeParameters();
        } else {
            actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
        }
        List<Class<?>> typeArgumentsAsClasses = new ArrayList<Class<?>>();
        // resolve types by chasing down type variables.
        for (Type baseType : actualTypeArguments) {
            while (resolvedTypes.containsKey(baseType)) {
                baseType = resolvedTypes.get(baseType);
            }
            typeArgumentsAsClasses.add(getClass(baseType));
        }
        return typeArgumentsAsClasses;
    }
  }

@Ivan Matavulj 2015-08-15 13:02:01

At which specific line in this code are actual, run-time type parameters being read ?

@Ondrej Bozek 2016-09-13 14:44:15

here? Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();

@Matthias M 2013-01-01 14:20:33

This is my solution:

import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;

public class GenericClass<T extends String> {

  public static void main(String[] args) {
     for (TypeVariable typeParam : GenericClass.class.getTypeParameters()) {
      System.out.println(typeParam.getName());
      for (Type bound : typeParam.getBounds()) {
         System.out.println(bound);
      }
    }
  }
}

@Adam Arold 2013-09-04 14:04:46

This is not an answer for this question.

@Matthias M 2014-01-24 08:30:40

My code is not the exact solution for the question. It returns the generic type parameters of the class, but not the actual type of T. But it may be helpful for others who stumple upon the question and are looking for my solution.

@Gorky 2014-07-01 22:36:40

getClass().getGenericSuperclass() will achieve the same effect.

@josefx 2010-08-04 08:59:40

Java generics are mostly compile time, this means that the type information is lost at runtime.

class GenericCls<T>
{
    T t;
}

will be compiled to something like

class GenericCls
{
   Object o;
}

To get the type information at runtime you have to add it as an argument of the ctor.

class GenericCls<T>
{
     private Class<T> type;
     public GenericCls(Class<T> cls)
     {
        type= cls;
     }
     Class<T> getType(){return type;}
}

Example:

GenericCls<?> instance = new GenericCls<String>(String.class);
assert instance.getType() == String.class;

@naXa 2014-12-10 08:01:46

private final Class<T> type;

@Pawel Cioch 2015-02-21 18:27:01

How can I create an array type from it: Type t = //String[]

@josefx 2015-02-22 17:02:15

@PawelCioch java.lang.reflect.Array.newInstance(elementtype, length); hope this helps (javadoc can be found here docs.oracle.com/javase/8/docs/api/java/lang/reflect/… )

@josefx 2015-02-23 09:24:46

@PawelCioch missed a .getClass() to get the type from the created array. There doesn't seem to be a direct way to get an array class. Most Java collections just use Object[] instead.

@FrVaBe 2010-08-04 08:53:20

I have seen something like this

private Class<T> persistentClass;

public Constructor() {
    this.persistentClass = (Class<T>) ((ParameterizedType) getClass()
                            .getGenericSuperclass()).getActualTypeArguments()[0];
 }

in the hibernate GenericDataAccessObjects Example

@Jonathan 2011-08-19 04:34:07

This technique works where the type parameter is defined on the immediate superclass, but it fails if the type parameter is defined elsewhere in the type hierarchy. For handling more complex cases something like TypeTools can be used. The docs include an example of a more sophisticated Generic DAO.

@Siu Ching Pong -Asuka Kenji- 2015-01-18 05:44:49

This only returns the actual type parameters used when a CLASS implements / extends something that has generic declarations, it does not return the actual type parameters used when an INSTANCE is instantiated. In other words, it CAN tell that in class A implements Comparable<String>, the actual type parameter is String, but it CANNOT tell that in Set<String> a = new TreeSet<String>(), the actual type parameter is String. In fact, the type parameter information is "erased" after compilation, as explained in other answers.

@mailmindlin 2015-02-05 16:54:06

You can also get a generic return type with something like this: <TYPE> TYPE getType(){return ((ParameterizedType)(new ArrayList<TYPE>()).getClass().getGenericSuperclass()).getAct‌​ualTypeArguments()[0‌​].getClass();} (sorry for the bad formatting). As far as I can tell, Lists don't always lose their generic types at runtime.

@Tomáš Zato - Reinstate Monica 2015-05-01 13:14:24

I am getting java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType for this answer.

@yunspace 2015-08-19 00:16:18

This approach can also be achieved using Class-Mate from the Jackson folks. I wrote a gist here gist.github.com/yunspace/930d4d40a787a1f6a7d1

@ieXcept 2016-06-22 12:17:21

@yunspace could you please provide the link to that library?

@yunspace 2016-06-23 13:53:56

@ieXcept class-mate is here github.com/FasterXML/java-classmate

@markdsievers 2016-10-19 03:23:22

@yunspace Nice recommendation. For me the solution to get the erased type for clazz inside a method like public void work(Class<T> clazz) was to use: new TypeResolver().resolve(clazz).getErasedType().

@AndrewMcCoist 2017-02-13 18:39:02

@TomášZato Calling simply the code above returned the same exception for me. I know it's a bit late, but anyway, in my case, I had to call (Class<T>) ((ParameterizedType)getClass().getSuperclass().getGenericSup‌​erclass()).getActual‌​TypeArguments() to get to actual type arguments.

@Nikolay Chernov 2017-02-16 13:13:46

Nice hack! Helped me a lot in my tests!

@Rosberg Linhares 2019-05-09 20:12:36

I am getting the same error as @TomášZato . My context is JUnit test execution. Any thoughts?

@andrewmu 2010-08-04 08:50:20

You can't. If you add a member variable of type T to the class (you don't even have to initialise it), you could use that to recover the type.

@andrewmu 2010-08-04 13:53:34

Oops, ok. You do have to initialise it from a constructor.

Related Questions

Sponsored Content

67 Answered Questions

[SOLVED] How do I generate random integers within a specific range in Java?

  • 2008-12-12 18:20:57
  • user42155
  • 3941341 View
  • 3402 Score
  • 67 Answer
  • Tags:   java random integer

7 Answered Questions

[SOLVED] How do I use reflection to call a generic method?

58 Answered Questions

[SOLVED] How do I read / convert an InputStream into a String in Java?

19 Answered Questions

[SOLVED] How to get a class instance of generics type T

  • 2010-08-09 06:58:45
  • robinmag
  • 650248 View
  • 667 Score
  • 19 Answer
  • Tags:   java generics

30 Answered Questions

[SOLVED] How to create a generic array in Java?

38 Answered Questions

[SOLVED] Why use getters and setters/accessors?

27 Answered Questions

[SOLVED] Create instance of generic type in Java?

  • 2008-09-16 18:04:28
  • David Citron
  • 437632 View
  • 558 Score
  • 27 Answer
  • Tags:   java generics

16 Answered Questions

[SOLVED] How to get the type of T from a member of a generic class or method?

  • 2009-02-17 15:24:36
  • Patrick Desjardins
  • 604830 View
  • 653 Score
  • 16 Answer
  • Tags:   c# .net generics

19 Answered Questions

[SOLVED] How to Sort a List<T> by a property in the object

19 Answered Questions

[SOLVED] How do I make the method return type generic?

Sponsored Content