简体   繁体   English

如何获取Java中通用接口实现的方法对象

[英]How to obtain method object for generic interface implementation in Java

In my case I want to find out if apply method's parameter for given implementation of Guava Function interface is annotated @Nullable . 在我的情况下,我想确定Guava Function接口的给定实现的apply方法的参数是否@Nullable注释。 Method to be implemented: 实施方法:

boolean isNullableArgument(Class<? extends Function<?,?>> function);

I don't know how to get implemented apply method from function class. 我不知道如何从function类中实现apply方法。


Eg there could be Function implementations like this: 例如,可能有如下的Function实现:

new Function<String,Integer>() {
    public Integer apply(String input) { … }
    public Integer apply(Integer input) { … }
}

Here's a quick and dirty solution. 这是一个快速而肮脏的解决方案。 Don't copy and paste it directly - it's only meant as an example to get you started. 不要直接复制和粘贴它-这只是作为入门的示例。

static boolean applyHasAnnotation(
        @SuppressWarnings("rawtypes") final Class<? extends Function> functionType,
        final Class<? extends Annotation> annotationType
) throws SecurityException, NoSuchMethodException {
    //for each directly implemented interface,
    for (final Type interfaceType : functionType.getGenericInterfaces()) {
        //if the interface is parameterized,
        if (interfaceType instanceof ParameterizedType) {
            final ParameterizedType genericInterfaceType = (ParameterizedType)interfaceType;
            //if the interface is Function
            if (genericInterfaceType.getRawType() == Function.class) {
                //get the type argument for T
                final Type inputType = genericInterfaceType.getActualTypeArguments()[0];
                //get its raw type
                final Class<?> rawInputType =
                        (inputType instanceof ParameterizedType)
                        ? (Class<?>)((ParameterizedType)inputType).getRawType()
                        : (Class<?>)inputType;
                //use it to find the apply implementation
                final Method applyMethod = functionType.getDeclaredMethod("apply", rawInputType);
                //for each annotation on its first (and only) parameter,
                for (final Annotation inputAnnotation : applyMethod.getParameterAnnotations()[0]) {
                    //if its type is the specified annotation type, return true
                    if (inputAnnotation.annotationType() == annotationType) {
                        return true;
                    }
                }
                return false;
            }
        }
    }
    //a more complicated inheritance hierarchy has defeated us
    throw new IllegalArgumentException("Function info not found.");
}

In actuality, you'll want to code the various concerns separately: 实际上,您将需要分别编码各种问题:

  • finding the generic interface on the implementing type 在实现类型上找到通用接口
  • looking up the F type argument to the generic interface 在通用接口上查找F类型参数
  • looking up the apply implementation 查找apply实施
  • checking its parameter for a given annotation 检查其参数是否有给定注释

As pointed out in the code, this solution easily breaks for more complicated type hierarchies, for example: 如代码中所指出的,此解决方案很容易打破更复杂的类型层次结构,例如:

abstract class LongFunction<T> implements Function<Long, T> { }

A new LongFunction<String> { } would be a Function<Long, String> but the above method would not location the generic Function interface on its runtime type. new LongFunction<String> { }将是Function<Long, String>但是上述方法不会将泛型Function接口放置在其运行时类型上。

The solution is: 解决方案是:

import com.google.common.base.Function;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Map;
import javax.annotation.Nullable;
import org.apache.commons.lang3.reflect.TypeUtils;

public class FunkUtils { private FunkUtils() {}

    public static boolean isNullableArgument(Class<? extends Function> functionClass) throws Exception {
        Map<TypeVariable<?>,Type> typeArgs = TypeUtils.getTypeArguments(functionClass, Function.class);
        TypeVariable<?> argTypeParam = Function.class.getTypeParameters()[0];
        Type argType = typeArgs.get(argTypeParam);
        Class argClass = TypeUtils.getRawType(argType, null);
        Method applyMethod = functionClass.getDeclaredMethod("apply", argClass);
        Annotation[] argAnnos = applyMethod.getParameterAnnotations()[0];
        for (int i = 0; i < argAnnos.length; i++) {
            if (argAnnos[i] instanceof Nullable) return true;
        }
        return false;
    }
}

There is a bug in TypeUtils.getTypeArguments in commons-lang3 version 3.1, but it is fixed in 3.2, that is under development now. commons-lang3版本3.1中的TypeUtils.getTypeArguments中有一个错误,但在3.2中已修复,该错误目前正在开发中。

If I got you question right, you want to do some validation of the annotation in the apply method. 如果我提出正确的问题,那么您想对apply方法中的注释进行一些验证。 You would need to use reflection this case (specially this method ). 这种情况下,您将需要使用反射(特别是此方法 )。 It would be something like (I will just make a draft omitting the exceptions): 就像是这样(我将草拟一个省略例外的草稿):

this.getClass().getMethod("apply", parameter.getClass()).getParameterAnnotations()

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

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