我有这个界面:
public interface EventHandler<T extends Event> {
void handle(T event);
}
这个类实现它:
public class MyEventHandler implements EventHandler<MyEvent> {
@Override
public void handle(MyEvent event) {
//do something
}
}
鉴于:
Class myEventHandlerClass = getClazz();
在此段中,T
参数为MyEvent
,这是Event
的具体实现。如何使用反射获得这个?
我想要这样的事情:
Class myEventHandlerClass = getClazz();
Method handleMethod = myEventhandlerClass.getDeclaredMethod("handle");
Class<?>[] params = method.getParameterTypes();
Class<?> eventConcreteType = params[0];
但myEventhandlerClass.getDeclaredMethod("handle");
抛出NoSuchMethodException
,因为我没有指定参数类型,因为我只知道这是Event
的具体实现,但我不知道哪个。< / p>
答案 0 :(得分:5)
通过通用接口解析T
的类型。 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:请记住,acutalTypeArguments的类型为Type
。它们不能是Class
。在您的情况下,它是一个类,因为您的类型定义是EventHandler<MyEvent>
。
答案 1 :(得分:0)
当尝试使用泛型和反射做任何不平凡的事情时,请考虑Guava的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());
}
(请注意TypeToken
返回的findEventType()
可能包含比Class
所能表示的更丰富的类型信息;这就是调用者决定是否通过{{1}简化它的原因}。)