Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java generics, get Class<T> of generic parameter

Tags:

java

generics

I have an abstract class:

public abstract class RootProcessor<T> {     Class<T> clazz; } 

I need to fill ClassT clazz; with the children of RootProcessor - every child has its own T

I found only one solution, but it needs compiler argument -Xlint:unchecked

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

Is this the best solution? Can we do the same without -Xlint:unchecked ?

like image 306
Victor Mezrin Avatar asked May 28 '13 18:05

Victor Mezrin


People also ask

How do you find the class name for a generic type?

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. ...and you get the name of the subclass (if any).

How do you determine what type a generic parameter T is?

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.

What is T in generics in Java?

It specifies the type parameters (also called type variables) T1, T2, ..., and Tn. To update the Box class to use generics, you create a generic type declaration by changing the code "public class Box" to "public class Box<T>". This introduces the type variable, T, that can be used anywhere inside the class.

What is the difference between T and E in Java generics?

Well there's no difference between the first two - they're just using different names for the type parameter ( E or T ). The third isn't a valid declaration - ? is used as a wildcard which is used when providing a type argument, e.g. List<?>


2 Answers

The typesafe, but boilerplatey way to do this is to pass the Class<T> token "where the compiler can see it":

public abstract class RootProcessor<T> {     Class<T> clazz;      protected RootProcessor<T>(Class<T> clazz) {         this.clazz = clazz;     } }  public class FooProcessor extends RootProcessor<Foo> {     public FooProcessor() {         super(Foo.class);     } } 

If you're doing an unchecked cast but you "know what you're doing" and want the compiler to stop complaining, the correct approach would be localising the non-type-safe-but-you-know-they-work bits and using @SuppressWarnings:

public abstract class RootProcessor<T> {     Class<T> clazz;     { initClazz(); }      @SuppressWarnings("unchecked")     private void initClazz() {         // the usual verbiage you already have in your question         this.clazz = this.getClass().getGenericSuperclass().yadda().blah();     } } 

(I won't hold this against you :P)

like image 73
millimoose Avatar answered Sep 19 '22 13:09

millimoose


There is a post of the same subject: Reflecting generics

And a class that implement it:TypeArgumentsUtils.java

An example is in the unit test.

So if you have this class:

public class BarProcessor extends RootProcessor<Bar> {     public BarProcessor() {     } } 

than you would get the first parameter with:

Class barClass = TypeArgumentsUtils.getFirstTypeArgument(         RootProcessor.class, BarProcessor.class); 
like image 26
Basilios Raptis Avatar answered Sep 19 '22 13:09

Basilios Raptis