Java 8:将lambda转换为包含闭包的Method实例 [英] Java 8: convert lambda to a Method instance with closure included

查看:134
本文介绍了Java 8:将lambda转换为包含闭包的Method实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(这很难搜索,因为结果全都与方法参考"有关)

(This is difficult to search because results are all about "method reference")

我想为lambda表达式获取一个Method实例,以与基于传统反射的API一起使用.应该包含Clousure,因此调用thatMethod.invoke(null, ...)应该与调用lambda具有相同的效果.

I want to get a Method instance for a lambda expression for use with a legacy reflection-based API. The clousure should be included, so calling thatMethod.invoke(null, ...) should have the same effect as calling the lambda.

我查看了 MethodHandles.Lookup ,但似乎只与反向转换有关.但是我猜想

I have looked at MethodHandles.Lookup, but it only seems to be relevant for the reverse transform. But I guess the bind method may help to include the clousure?

说我是lambda专家:

Say I have am lambda experssion:

Function<String, String> sayHello = name -> "Hello, " + name;

,我有一个旧式框架( SpEL )具有类似

and I have a legacy framework (SpEL) that has an API like

registerFunction(String name, Method method)

,它将在没有this参数的情况下调用给定的Method(即,假设方法为静态).因此,我需要获得一个特殊的Method实例,其中包括lambda逻辑+ clousure数据.

which will call the given Method with no this argument (i.e. Method assumed to be static). So I'll need to get a special Method instance that includes the lambda logic + the clousure data.

推荐答案

如果您找不到优雅的方法,这就是丑陋的方法( Idone ).涉及反射时通常会发出警告:在将来的发行版中可能会中断.

In case you don't find an elegant way, here is the ugly way (Ideone). Usual warning when reflection is involved: may break in future releases etc.

public static void main(String[] args) throws Exception {
  Function<String, String> sayHello = name -> "Hello, " + name;
  Method m = getMethodFromLambda(sayHello);
  registerFunction("World", m);
}

static void registerFunction(String name, Method method) throws Exception {
  String result = (String) method.invoke(null, name);
  System.out.println("result = " + result);
}

private static Method getMethodFromLambda(Function<String, String> lambda) throws Exception {
  Constructor<?> c = Method.class.getDeclaredConstructors()[0];
  c.setAccessible(true);
  Method m = (Method) c.newInstance(null, null, null, null, null, 0, 0, null, null, null, null);
  m.setAccessible(true); //sets override field to true

  //m.methodAccessor = new LambdaAccessor(...)
  Field ma = Method.class.getDeclaredField("methodAccessor");
  ma.setAccessible(true);
  ma.set(m, new LambdaAccessor(array -> lambda.apply((String) array[0])));

  return m;
}

static class LambdaAccessor implements MethodAccessor {
  private final Function<Object[], Object> lambda;
  public LambdaAccessor(Function<Object[], Object> lambda) {
    this.lambda = lambda;
  }

  @Override public Object invoke(Object o, Object[] os) {
    return lambda.apply(os);
  }
}

这篇关于Java 8:将lambda转换为包含闭包的Method实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆