java在运行时收到谓词函数的名称时,如何将一个函数作为谓词传递给另一个函数?
我收到了在运行时用作biPredicate的函数名。我想通过这个双向预测和评估,基本上过滤得到结果。 下面是我的实用程序,它定义了biPredicates。我尝试使用MethodHandle和Lambda函数。当我使用
new FilterUtility().execute("genericFilter");
I get java.lang.AbstractMethodError
public class FilterUtility {
public void execute(String filterName) throws Throwable {
ActualBean beanObject = ActualBean.builder().param1("true").param2("false").build();
MethodType methodType = MethodType.methodType(boolean.class, Object.class, Object.class);
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodHandle handle = lookup.findStatic(FilterUtility.class, filterName, methodType);
BiPredicate<Object, Object> f = (BiPredicate<Object, Object>) LambdaMetafactory.metafactory(lookup,
"test",
MethodType.methodType(BiPredicate.class),
methodType.generic(),
handle,
methodType)
.getTarget()
.invokeExact();
resolve(beanObject, new HashMap<>(), f);
}
public static <SourceObject, TemplateObject> Map<String, String> resolve(SourceObject src,
TemplateObject template,
BiPredicate<SourceObject, TemplateObject> p) {
if (p.test(src, template))
return new HashMap<>();
return null;
}
public static <SourceObject, TemplateObject> boolean genericFilter(SourceObject x, TemplateObject y) {
ObjectMapper ob = new ObjectMapper();
Map<String, Object> source = ob.convertValue(x, Map.class);
Map<String, Object> template = ob.convertValue(y, Map.class);
for (Map.Entry<String, Object> entry : template.entrySet()) {
if (!source.get(entry.getKey()).equals(entry.getValue()))
return false;
}
return true;
}
}
当我将execute的实现更改为following时,不会出现异常
public void execute(String filterName) throws Throwable {
ActualBean beanObject = ActualBean.builder().param1("true").param2("false").build();
resolve(beanObject, new HashMap<>(), FilterUtility::genericFilter); }
这让我相信,我试图找到具有名称的函数并将其作为双预测发送的方式有问题
# 1 楼答案
您正在调用方法
methodType.generic()
,该方法将用java.lang.Object
替换所有参数类型和返回类型,包括基元类型。因此,您正在将目标方法的签名(Object,Object)->boolean
转换为(Object,Object)->Object
,有效地创建了一个带有方法Object test(Object,Object)
的类,该方法将调用您的目标方法并将结果框起来lambda元工厂不会检查此类类型不匹配。因此,当您试图在生成的类上调用
BiPredicate
的方法boolean test(Object,Object)
时,将抛出一个错误正确的方法是
methodType.erase()
,它将用java.lang.Object
替换所有引用类型,但保持原语类型不变。不过,在这种特定情况下,根本不需要转换方法类型,因为目标方法的类型已经是(Object,Object)->boolean
,所以用methodType
替换methodType.generic()
也可以