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
?
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).
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.
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.
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<?>
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)
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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With