106

I got a list, programmed like this: public class MyList<T>. Is there any way to use the T variable to get the name of class (so I can, from within MyList, know if T is String, Socket, etc.)?

EDIT: Nevermind, found the answer here.

Community
  • 1
  • 1
ryyst
  • 9,563
  • 18
  • 70
  • 97

5 Answers5

139

Short answer: You can't.

Long answer:

Due to the way generics is implemented in Java, the generic type T is not kept at runtime. Still, you can use a private data member:

public class Foo<T> 
{
    private Class<T> type;

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

Usage example:

Foo<Integer> test = new Foo<Integer>(Integer.class);
Andrew
  • 5,839
  • 1
  • 51
  • 72
duffymo
  • 305,152
  • 44
  • 369
  • 561
75

I like the solution from

http://www.nautsch.net/2008/10/28/class-von-type-parameter-java-generics/

public class Dada<T> {

    private Class<T> typeOfT;

    @SuppressWarnings("unchecked")
    public Dada() {
        this.typeOfT = (Class<T>)
                ((ParameterizedType)getClass()
                .getGenericSuperclass())
                .getActualTypeArguments()[0];
    }
...
P̲̳x͓L̳
  • 3,615
  • 3
  • 29
  • 37
wutzebaer
  • 14,365
  • 19
  • 99
  • 170
27

You are seeing the result of Type Erasure. From that page...

When a generic type is instantiated, the compiler translates those types by a technique called type erasure — a process where the compiler removes all information related to type parameters and type arguments within a class or method. Type erasure enables Java applications that use generics to maintain binary compatibility with Java libraries and applications that were created before generics.

For instance, Box<String> is translated to type Box, which is called the raw type — a raw type is a generic class or interface name without any type arguments. This means that you can't find out what type of Object a generic class is using at runtime.

This also looks like this question which has a pretty good answer as well.

Community
  • 1
  • 1
Andrew White
  • 52,720
  • 19
  • 113
  • 137
4

I'm not 100% sure if this works in all cases (needs at least Java 1.5):

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

public class Main 
{
    public class A
    {   
    }

    public class B extends A
    {       
    }


    public Map<A, B> map = new HashMap<Main.A, Main.B>();

    public static void main(String[] args) 
    {

        try
        {
            Field field = Main.class.getField("map");           
            System.out.println("Field " + field.getName() + " is of type " + field.getType().getSimpleName());

            Type genericType = field.getGenericType();

            if(genericType instanceof ParameterizedType)
            {
                ParameterizedType type = (ParameterizedType) genericType;               
                Type[] typeArguments = type.getActualTypeArguments();

                for(Type typeArgument : typeArguments) 
                {   
                    Class<?> classType = ((Class<?>)typeArgument);                  
                    System.out.println("Field " + field.getName() + " has a parameterized type of " + classType.getSimpleName());
                }
            }
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }    
}

This will output:

Field map is of type Map
Field map has a parameterized type of A
Field map has a parameterized type of B

Paul Bellora
  • 54,340
  • 18
  • 130
  • 181
esaj
  • 15,875
  • 5
  • 38
  • 52
  • Once I tried to do similar during refactoring of General DAO, so I went through some similar code samples. Don't remember why, but I decided not to go with such approach (I think it didn't work well in all cases, maybe class hierarchy was mandatory). Your example does work :) +1 P.S. Some extended tutorial I've found: http://www.artima.com/weblogs/viewpost.jsp?thread=208860 – Art Licis Jan 29 '11 at 14:38
  • I found the original article where I lifted this from (the example above is extracted from one of our work-projects): http://tutorials.jenkov.com/java-reflection/generics.html#fieldtypes The article says this only works with public-fields, but that's not true, you can access protected and private fields via reflection too (just use getDeclaredField instead of getField) – esaj Jan 29 '11 at 14:45
  • 2
    This does not answer the question. This gets the type used in declaring a field. How is this relevant? – newacct Aug 03 '12 at 23:09
3

I'm able to get the Class of the generic type this way:

class MyList<T> {
  Class<T> clazz = (Class<T>) DAOUtil.getTypeArguments(MyList.class, this.getClass()).get(0);
}

You need two functions from this file: http://code.google.com/p/hibernate-generic-dao/source/browse/trunk/dao/src/main/java/com/googlecode/genericdao/dao/DAOUtil.java

For more explanation: http://www.artima.com/weblogs/viewpost.jsp?thread=208860

Peter Tseng
  • 13,613
  • 4
  • 67
  • 57