将LambdaMetafactory.metafactory()用于普通的非静态getter

时间:2018-01-11 09:14:19

标签: java reflection lambda methodhandle

我有一个简单的Person课程,其中getName()会返回String

public class Person {

    public String getName() {...}

}

如何在运行时使用LambdaMetafactory为非静态方法getName()创建lambda?

这是我到目前为止所得到的:

public class MyMain {

    public static void main(String[] args) throws Throwable {
        GetterFunction getterFunction;

        MethodHandles.Lookup lookup = MethodHandles.lookup();
        String invokedMethodName = "getName";
        MethodType invokedType = MethodType.methodType(GetterFunction.class);
        MethodType methodType = MethodType.methodType(Object.class);
        MethodHandle virtual = lookup.findVirtual(Person.class, "getName", MethodType.methodType(String.class));
        CallSite site = LambdaMetafactory.metafactory(lookup,
                invokedMethodName,
                invokedType,
                methodType,
                virtual,
                methodType);
        getterFunction = (GetterFunction) site.getTarget().invokeExact();
        System.out.println(getterFunction.getName(new Person("Ann")));
    }

    @FunctionalInterface
    private interface GetterFunction {

        String getName(Person person);

    }

}

引发:

java.lang.invoke.LambdaConversionException: Incorrect number of parameters for instance method invokeVirtual foo.Person.getName:()String; 0 captured parameters, 0 functional interface method parameters, 0 implementation parameters
    at java.lang.invoke.AbstractValidatingLambdaMetafactory.validateMetafactoryArgs(AbstractValidatingLambdaMetafactory.java:193)
    at java.lang.invoke.LambdaMetafactory.metafactory(LambdaMetafactory.java:303)

2 个答案:

答案 0 :(得分:2)

这有效:

public class MyMain {

    public static void main(String[] args) throws Throwable {
        GetterFunction getterFunction;
        final MethodHandles.Lookup lookup = MethodHandles.lookup();
        MethodType methodType = MethodType.methodType(String.class, Person.class);
        final CallSite site = LambdaMetafactory.metafactory(lookup,
                "invoke",
                MethodType.methodType(GetterFunction.class),
                methodType,
                lookup.findVirtual(Person.class, "getName", MethodType.methodType(String.class)),
                methodType);
        getterFunction = (GetterFunction) site.getTarget().invokeExact();
        System.out.println(getterFunction.invoke(new Person("Ann")));
    }

    @FunctionalInterface
    interface GetterFunction {

        String invoke(final Person callable);
    }

}

答案 1 :(得分:1)

只需扩展Geoffrey De Smet的答案,以显示使用Function会是什么样子,因为需要进行一些小的调整:

Country