[英]Java - How to pass unknown implementation of interface to generic method
[英]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中已修复,该错误目前正在开发中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.