Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get type name for generic parameter of generic class [duplicate]

Tags:

java

generics

I have a small problem in java while using genericity. I have a class A :

public class A<T>

In a method of A, I need to get the type name of T. Is there a way to find the string s using T ?

(If I create A<String> temp = new A<String>();, I want to be able to get java.lang.String at one point - I have to use genericity because one of my methods will have to return a List<T>).

This seems quite easy but I do not see how to do it.

like image 968
ThR37 Avatar asked Jul 08 '11 12:07

ThR37


People also ask

How do you find the type of generic type?

Use the IsGenericType property to determine whether the type is generic, and use the IsGenericTypeDefinition property to determine whether the type is a generic type definition. Get an array that contains the generic type arguments, using the GetGenericArguments method.

Can a generic class have multiple generic parameters?

A Generic class can have muliple type parameters.

How do you provide a generic parameterized type?

In order to use a generic type we must provide one type argument per type parameter that was declared for the generic type. The type argument list is a comma separated list that is delimited by angle brackets and follows the type name. The result is a so-called parameterized type.

Can dynamic type be used for generic?

Not really. You need to use reflection, basically. Generics are really aimed at static typing rather than types only known at execution time.


2 Answers

You can't do this in general because of type erasure - an instance of A<String> doesn't know the type of T. If you need it, one way is to use a type literal:

public class A<T>
{
    private final Class<T> clazz;

    public A<T>(Class<T> clazz)
    {
        this.clazz = clazz;
    }

    // Use clazz in here
}

Then:

A<String> x = new A<String>(String.class);

It's ugly, but that's what type erasure does :(

An alternative is to use something like Guice's TypeLiteral. This works because the type argument used to specify a superclass isn't erased. So you can do:

A<String> a = new A<String>() {};

a now refers to a subclass of A<String>, so by getting a.getClass().getSuperClass() you can eventually get back to String. It's pretty horrible though.

like image 89
Jon Skeet Avatar answered Oct 12 '22 22:10

Jon Skeet


You can get the name of the generics from the subclass. See this example. We Define a parent class like this:

public class GetTypeParent<T> {

    protected String getGenericName()
    {
        return ((Class<T>) ((ParameterizedType) getClass()
                .getGenericSuperclass()).getActualTypeArguments()[0]).getTypeName();
    }
}

We then define its child class in this way:

public class GetTypeChild extends GetTypeParent<Integer> {
    public static void main(String[] args) {
        GetTypeChild getTypeChild = new GetTypeChild();
        System.out.println(getTypeChild.getGenericName());
    }
}

You can see that in the main method, or in any instance method, I am capable to get the name of the generics type, in this case the main will print: java.lang.Integer.

like image 35
Enrico Giurin Avatar answered Oct 12 '22 22:10

Enrico Giurin