I have this interface:
public interface EventHandler<T extends Event> {
void handle(T event);
}
And this class implementing it:
public class MyEventHandler implements EventHandler<MyEvent> {
@Override
public void handle(MyEvent event) {
//do something
}
}
In this clase, T
parameter is MyEvent
, that is a concrete implementation of Event
. How can obtain this using reflection?
Resolve the type of T
by the generic interface. E.g.
public interface SomeInterface<T> {
}
public class SomeImplementation implements SomeInterface<String> {
public Class getGenericInterfaceType(){
Class clazz = getClass();
ParameterizedType parameterizedType = (ParameterizedType) clazz.getGenericInterfaces()[0];
Type[] typeArguments = parameterizedType.getActualTypeArguments();
Class<?> typeArgument = (Class<?>) typeArguments[0];
return typeArgument;
}
}
public static void main(String[] args) {
SomeImplementation someImplementation = new SomeImplementation();
System.out.println(someImplementation.getGenericInterfaceType());
}
PS: Keep in mind that the acutalTypeArguments are of type Type
. They must not be a Class
. In your case it is a Class because your type definition is EventHandler<MyEvent>
.
When trying to do anything non-trivial with generics and reflection, consider Guava's TypeToken
:
private interface Event {}
private interface EventHandler<T extends Event> {
void handle(T event);
}
TypeToken<?> findEventType(final Class<? extends EventHandler> handlerClass) throws Exception {
final TypeToken<? extends EventHandler> handlerTypeToken = TypeToken.of(handlerClass);
final Invokable<? extends EventHandler,Object> method = handlerTypeToken.method(EventHandler.class.getDeclaredMethod("handle", Event.class));
return method.getParameters().get(0).getType();
}
public void testExploreGuavaTypeTokens() throws Exception {
class MyEvent implements Event {}
class MyEventHandler implements EventHandler<MyEvent> {
@Override public void handle(final MyEvent event) {}
}
assertEqual(MyEvent.class, findEventType(MyEventHandler.class).getRawType());
}
(Note that the TypeToken
returned by findEventType()
could contain much richer type information than a Class
can represent; that's why it's the caller's decision whether to simplify it via getRawType()
.)