获取lambda

简介: 获取lambda

处世让一步为高,退步即进步的张本;待人宽一分是福利人利己的根基。——洪自诚

昨天说了获取lambda代理

今天获取实际lambda对象

重要的是这个函数java.lang.invoke.LambdaMetafactory#metafactory以及altMetafactory

我们在昨天的基础上,进行获取

@Test
@SneakyThrows
void testVirtual() {
    final MethodHandle virtual = MethodHandles.lookup().findVirtual(LambdaExecutable.class, "getName", MethodType.methodType(String.class));
    final SerFunc<LambdaExecutable, String> proxy = MethodHandleProxies.asInterfaceInstance(SerFunc.class, virtual);
    InvocationHandler handler = Proxy.getInvocationHandler(proxy);
    MethodHandle methodHandle = ReflectHelper.getFieldValue(handler, "val$target");
    final CallSite callSite = LambdaMetafactory.altMetafactory(
            MethodHandles.lookup(),
            "apply",
            MethodType.methodType(SerFunc.class),
            MethodType.methodType(Object.class, Object.class),
            methodHandle,
            MethodType.methodType(String.class, LambdaExecutable.class),
            LambdaMetafactory.FLAG_SERIALIZABLE
    );
    final MethodHandle target = callSite.getTarget();
    final SerFunc<LambdaExecutable, String> invoke = (SerFunc<LambdaExecutable, String>) target.invoke();
    final LambdaExecutable executable = new LambdaExecutable();
    executable.setName("test");
    Assertions.assertEquals("test", invoke.apply(executable));
    Assertions.assertEquals("getName", LambdaHelper.resolve(invoke).getName());
}


进一步封装后:

public static <T> T revert(Class<T> clazz, Executable executable) {
        final Method funcMethod = Steam.of(clazz.getMethods()).findFirst(method -> Modifier.isAbstract(method.getModifiers()))
                .orElseThrow(() -> new UtilException("not a functional interface"));
        final MethodHandle implMethod;
        final MethodType instantiatedMethodType;
        if (executable instanceof Method) {
            final Method method = (Method) executable;
            implMethod = ((SerSupp<MethodHandle>) () -> MethodHandles.lookup().unreflect(method)).get();
            instantiatedMethodType = MethodType.methodType(method.getReturnType(), method.getDeclaringClass(), method.getParameterTypes());
        } else {
            final Constructor<?> constructor = (Constructor<?>) executable;
            implMethod = ((SerSupp<MethodHandle>) () -> MethodHandles.lookup().unreflectConstructor(constructor)).get();
            instantiatedMethodType = MethodType.methodType(constructor.getDeclaringClass(), constructor.getParameterTypes());
        }
        final CallSite callSite = ((SerSupp<CallSite>) () ->
                Serializable.class.isAssignableFrom(clazz) ?
                        LambdaMetafactory.altMetafactory(
                                MethodHandles.lookup(),
                                funcMethod.getName(),
                                MethodType.methodType(clazz),
                                MethodType.methodType(funcMethod.getReturnType(), funcMethod.getParameterTypes()),
                                implMethod,
                                instantiatedMethodType,
                                LambdaMetafactory.FLAG_SERIALIZABLE
                        ) :
                        LambdaMetafactory.metafactory(
                                MethodHandles.lookup(),
                                funcMethod.getName(),
                                MethodType.methodType(clazz),
                                MethodType.methodType(funcMethod.getReturnType(), funcMethod.getParameterTypes()),
                                implMethod,
                                instantiatedMethodType
                        )
        ).get();
        final MethodHandle target = callSite.getTarget();
        return ((SerSupp<T>) () -> SerFunc.<Object, T>cast().apply(target.invoke())).get();
    }

使用方式:

@Test
void testRevert() {
    final LambdaExecutable getName = LambdaHelper.<SerFunc<LambdaExecutable, String>>resolve(LambdaExecutable::getName);
    final SerFunc<LambdaExecutable, String> revertedGetName = LambdaHelper.revert(SerFunc.class, getName.getExecutable());
    Assertions.assertEquals(revertedGetName.apply(getName), getName.getName());
    final LambdaExecutable constructor = LambdaHelper.<SerSupp<LambdaExecutable>>resolve(LambdaExecutable::new);
    final SerSupp<LambdaExecutable> revertedConstructor = LambdaHelper.revert(SerSupp.class, constructor.getExecutable());
    Assertions.assertEquals(LambdaExecutable.class, revertedConstructor.get().getClass());
}

源码地址:https://gitee.com/VampireAchao/stream-query

相关文章
|
7月前
lambda中orElse(null)使用
lambda中orElse(null)使用
163 0
|
Python
lambda
lambda 是一个匿名函数,它通常用于简化代码,使代码更简洁、易读。lambda 函数不需要显式地使用 def 关键字进行定义,可以直接在表达式中使用。它的语法如下:
177 6
|
SQL Java 程序员
聊聊lambda
聊聊lambda
48 1
|
7月前
|
C#
C# Lambda
C# Lambda
45 0
|
算法 编译器
【lambda函数】lambda()函数
【lambda函数】lambda()函数
|
设计模式 Java API
值得使用Lambda的8个场景,别再排斥它了!
前言 可能对不少人来说,Lambda显得陌生又复杂,觉得Lambda会导致代码可读性下降,诟病Lambda语法,甚至排斥。
|
算法 编译器 容器
lambda
lambda
110 0
|
Java 开发者
lambda让代码更优雅
Lambda表达式是Java 8中引入的一个重要特性,它允许开发者以更简洁的方式编写匿名函数,使得代码更加紧凑和易读。Lambda表达式是函数式编程的一种体现,可以将函数作为方法的参数传递,并且可以使用更简洁的语法实现函数式接口(只有一个抽象方法的接口)的实例化。Lambda表达式的语法形式为 (参数列表) -> {表达式或语句块}。
86 0
|
Serverless Go 云计算
Lambda
Lambda自制脑图
238 0
 Lambda