Reputation: 2847
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
?
Upvotes: 53
Views: 109417
Reputation: 73
As above you should use @SuppressWarnings
.
But I'd like to use TypeToken
in guava.
It can resolve generic type in inheritance.
package com.example.demo;
import com.google.common.reflect.TypeToken;
class A<A, B> {
}
class B<T> extends A<T, String> {
}
class C extends B<Long> {
}
public class Main {
public static void main(final String[] args) {
final var cTypeToken = TypeToken.of(C.class);
final TypeToken<? super C> aTypeToken = cTypeToken.getSupertype(A.class);
final TypeToken<?> resolved = aTypeToken.resolveType(A.class.getTypeParameters()[0]);
// java.lang.Long
System.out.println(resolved);
}
}
Upvotes: 0
Reputation: 31
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);
Upvotes: 3
Reputation: 39950
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)
Upvotes: 40