How can I obtain the type parameter of a generic interface from an implementing class?

前端 未结 2 1328
萌比男神i
萌比男神i 2021-01-12 14:53

I have this interface:

public interface EventHandler {
    void handle(T event);
}

And this class implementing it:

相关标签:
2条回答
  • 2021-01-12 15:03

    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>.

    0 讨论(0)
  • 2021-01-12 15:25

    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().)

    0 讨论(0)
提交回复
热议问题