繁体   English   中英

检查方法参数的通用类型

[英]Examine generic type of a method parameter

我不知道这是否可以用Java完成。 我找不到解决方案。

我想检查一个类中的所有方法,并找出带有通用信息的方法的参数。 例如,如果您有一个接口和一个类似于以下内容的实现者:

// Services are the objects i will examine

public interface Service<T extends DetailsModel> {
   public Response findObject(RequestEvent<T> event);
}

public interface SomeObjectService extends Service<SomeObject> {
   Response findObject(RequestEvent<SomeObject> event);
}

public class SomeObjectServiceImpl extends SomeObjectService  {
   public Response findObject(RequestEvent<SomeObject> event) {...}
}

// Events are the parameters of the services

public interface Event<T extends DetailsModel> {
   Callback getCallback()
}

public abstract class AbstractEvent<T> implements Event<T> {

  public Callback getCallback() {
     return null;
  }
}

public class RequestEvent<T> extends AbstractEvent<T> {
    Handle<T> t;

    public Handle<T> getHandle() {...}
}

在查看SomeObjectServiceImpl时,我尝试了各种方法来从RequestEvent中获取实际的T。 例如

public <D extends DetailsModel> void configure(Service<D> service) {
   Method[] allDeclaredMethods = service.getClass().getDeclaredMethods();

   for (Method declaredMethod : allDeclaredMethods) {
     try {
        Type[] parameterTypes = declaredMethod.getGenericParameterTypes();
        if (parameterTypes.length == 1) {
           Type parameterType = parameterTypes[0];
           if (Event.class.isAssignableFrom((Class<?>) parameterType)) {
              ParameterizedType type = ((ParameterizedType) ((Class) parameterType).getGenericSuperclass());
              Type genericType = type.getActualTypeArguments()[0];
              if (genericType != null && genericType instanceof Class) {
                 EventDescriber eventDescriber = new EventDescriber(
                       (Class<? extends Event>) parameterType,
                       (Class) genericType);
              }
           }
        } 
     } catch (Exception e) {
        logger.warn("Could not map " + declaredMethod, e);
     }
  }

然后,我希望对SomeObjectServiceImpl中的方法进行检查的结果是:

ServiceImpl:
  findObject: 
     RequestEvent
        SomeObject (I cant find this. Instead I find a TypeVariableImpl.)

您可以使用Java反射来做到这一点吗?

当然可以。 使用该Method检索[通用参数类型] [1]。

Method method = ServiceImpl.class.getMethod("doSomething",
            DoSomethingEvent.class);
ParameterizedType type = (ParameterizedType)method.getGenericParameterTypes()[0];

然后访问[原始类型] [2]和[实际类型参数] [3]。

type.getRawType();
type.getActualTypeArguments()[0]; // first type argument

这是一个有效的例子

public class Test {
    public static void main(String[] args) throws Exception {
        configure(new ServiceImpl());
    }

    public static <T> void configure(Service<T> service) {
        Method[] allDeclaredMethods = service.getClass().getDeclaredMethods();

        for (Method declaredMethod : allDeclaredMethods) {
            try {
                Class<?>[] parameterTypes = declaredMethod.getParameterTypes();
                if (parameterTypes.length == 1) {
                    Class<?> parameterType = parameterTypes[0];
                    if (Event.class.isAssignableFrom(parameterType)) {
                        ParameterizedType type = ((ParameterizedType) declaredMethod
                                .getGenericParameterTypes()[0]);
                        Type typeArgument = type.getActualTypeArguments()[0];
                        System.out.println("Parameter type: " + type.getRawType() + ", Generic type argument: " + typeArgument);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

interface Response {
}

interface Service<T> {
    public Response findObject(RequestEvent<T> event);
}

class ServiceImpl implements Service<SomeObject> {
    public Response findObject(RequestEvent<SomeObject> event) {
        return null;
    }

    public Response doSomething(DoSomethingEvent<SomethingAction> event) {
        return null;
    }
}

interface Event<T> {
}

interface SomethingAction {
}

class SomeObject {
}

class DoSomethingEvent<T> extends RequestEvent<T> {
}

interface Handle<T> {
}

class RequestEvent<T> implements Event<T> {
    Handle<T> t;

    public Handle<T> getHandle() {
        return null;
    }
}

它打印

Parameter type: class com.example.RequestEvent, Generic type argument: class com.example.SomeObject
Parameter type: class com.example.DoSomethingEvent, Generic type argument: interface com.example.SomethingAction

我只是做了同样的事情。 仅限于Iterable ,但反射代码将非常相似:

/**
 * Assuming the given method returns or takes an Iterable<T>, this determines the type T.
 * T may or may not extend WindupVertexFrame.
 */
private static Class typeOfIterable(Method method, boolean setter)
{
    Type type;
    if (setter) {
        Type[] types = method.getGenericParameterTypes();
        // The first parameter to the method expected to be Iterable<...> .
        if (types.length == 0)
            throw new IllegalArgumentException("Given method has 0 params: " + method);
        type = types[0];
    }
    else {
        type = method.getGenericReturnType();
    }

    // Now get the parametrized type of the generic.
    if (!(type instanceof ParameterizedType))
        throw new IllegalArgumentException("Given method's 1st param type is not parametrized generic: " + method);
    ParameterizedType pType = (ParameterizedType) type;
    final Type[] actualArgs = pType.getActualTypeArguments();
    if (actualArgs.length == 0)
        throw new IllegalArgumentException("Given method's 1st param type is not parametrized generic: " + method);

    Type t = actualArgs[0];
    if (t instanceof Class)
        return (Class<?>) t;

    if (t instanceof TypeVariable){
        TypeVariable tv =  (TypeVariable) actualArgs[0];
        AnnotatedType[] annotatedBounds = tv.getAnnotatedBounds();///
        GenericDeclaration genericDeclaration = tv.getGenericDeclaration();///
        return (Class) tv.getAnnotatedBounds()[0].getType();
    }

    throw new IllegalArgumentException("Unknown kind of type: " + t.getTypeName());
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM