反射投射java。朗,反思一下。方法创建一个函数接口
很难找到关于这个话题的任何线索。我能找到的只是关于将一个函数接口转换为另一个函数接口的问题,以及一些关于Java中类型转换的文章。不是我想要的
This问题是关于转换lambda → Method
,我想要相反的,将^{
我找到的方法是围绕Method#invoke
方法创建一个lambda适配器:
public void registerCallbacks(final Object annotated) {
Class clazz = annotated.getClass();
for (Method method : clazz.getDeclaredMethods()) {
if (method.isAnnotationPresent(Callback.class)) {
Callback registration = method.getAnnotation(Callback.class);
List<String> warnings = new ArrayList<>(3);
if (!Modifier.isPublic(method.getModifiers()))
warnings.add(String.format("Method %s must be public", method));
if (method.getParameterCount() != 1)
warnings.add(String.format("Method %s must consume only one argument", method));
if (method.getParameterCount() == 1 && !method.getParameterTypes()[0].equals(Integer.class))
warnings.add(String.format("Method %s must consume %s", method, Integer.class));
if (!warnings.isEmpty()) {
warnings.forEach(log::warn);
continue;
}
CALLBACKS_MAPPER.registerCallback((param) -> {
try {
method.invoke(annotated, param);
} catch (IllegalAccessException | InvocationTargetException e) {
// Should not happen due to checks before.
log.warn(String.format("Could not invoke %s on %s with %s", method, annotated, param), e);
}
});
log.info("Registered {} as a callback", method);
}
}
}
然而,我想避免写作
CALLBACKS_MAPPER.registerCallback((param) -> {
try {
method.invoke(annotated, param);
} catch (IllegalAccessException | InvocationTargetException e) {
// Should not happen due to checks before.
log.warn(String.format("Could not invoke %s on %s with %s", method, annotated, param), e);
}
});
支持更简单的东西,比如
CALLBACKS_MAPPER.registerCallback(SomeApacheLib.methodToFunction(annotated, method));
➥ 那么,有没有办法将旧的Java 1.1反射库映射到新的Java 8功能接口,或者是我太愚蠢了,而上面提到的使用lambda的解决方案就可以了
# 1 楼答案
如果你满足于在引擎盖下使用反射,只是不喜欢
try
/catch
周围的invoke
,你可以制作一个简单的实用函数,比如:这正是你想要的语法:
但是如果你想完全避免反射,你可以使用
LambdaMetafactory
来创建一个Consumer
:将
String
更改为您希望接受的回调。然后:当然,这里唯一正确的解决方案是重构代码,使用已知的回调接口,通常可以在该接口上调用定义的方法,而不是传递
Method