繁体   English   中英

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

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

在我的情况下,我想确定Guava Function接口的给定实现的apply方法的参数是否@Nullable注释。 实施方法:

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

我不知道如何从function类中实现apply方法。


例如,可能有如下的Function实现:

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

这是一个快速而肮脏的解决方案。 不要直接复制和粘贴它-这只是作为入门的示例。

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.");
}

实际上,您将需要分别编码各种问题:

  • 在实现类型上找到通用接口
  • 在通用接口上查找F类型参数
  • 查找apply实施
  • 检查其参数是否有给定注释

如代码中所指出的,此解决方案很容易打破更复杂的类型层次结构,例如:

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

new LongFunction<String> { }将是Function<Long, String>但是上述方法不会将泛型Function接口放置在其运行时类型上。

解决方案是:

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;
    }
}

commons-lang3版本3.1中的TypeUtils.getTypeArguments中有一个错误,但在3.2中已修复,该错误目前正在开发中。

如果我提出正确的问题,那么您想对apply方法中的注释进行一些验证。 这种情况下,您将需要使用反射(特别是此方法 )。 就像是这样(我将草拟一个省略例外的草稿):

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

暂无
暂无

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

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