有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java以编程方式创建Java8函数引用

只是一个理论问题,我目前没有实际的用例

假设一些my API接受函数引用作为参数,我希望通过“::”语法直接从代码中输入它,或者通过反射收集匹配的函数,存储在一些映射中并有条件地调用

可以通过编程将method转换为Consumer<String>

Map<String, Consumer<String>> consumers = new HashMap<>();
consumers.put("println", System.out::println);

Method method = PrintStream.class.getMethod("println", String.class);
consumers.put("println", makeFunctionReference(method));
...
myapi.feedInto(consumers.get(someInput.getConsumerId()));

更新

虽然对当前提供的答案中的解决方案不满意,但在得到关于LambdaMetaFactory的提示后,我尝试编译这段代码

public class TestImpl {
    public static void FnForString(String arg) {}
}

public class Test {
    void test() {
        List<String> strings = new ArrayList<>();
        Consumer<String> stringConsumer = TestImpl::FnForString;

        strings.stream().forEach(stringConsumer);
        strings.stream().forEach(TestImpl::FnForString);
        stringConsumer.accept("test");
    }
}

在向CFR反编译器中只提供了测试类之后,我得到了以下结果:

public class Test {
    void test() {
        ArrayList strings = new ArrayList();
        Consumer<String> stringConsumer = 
            (Consumer<String>)LambdaMetafactory.metafactory(
                null, null, null, 
                (Ljava/lang/Object;)V, 
                FnForString(java.lang.String), 
                (Ljava/lang/String;)V)();
        strings.stream().forEach(stringConsumer);
        strings.stream().forEach(
            (Consumer<String>)LambdaMetafactory.metafactory(
                null, null, null, 
                (Ljava/lang/Object;)V, 
                FnForString(java.lang.String ), 
                (Ljava/lang/String;)V)());
        stringConsumer.accept("test");
    }
}

由此我看到:

  • 这在某种程度上是有可能以“一行”的方式实现的
  • 不需要异常处理
  • 我不知道反编译器输出中的(Ljava/lang/Object;)V(和其他)是什么。它应该与metafactory()参数中的MethodType匹配。此外,反编译器中的任何一个都“吃/藏”了一些东西,但现在似乎在获取函数引用的过程中调用了一些方法
  • (offtop)即使在编译代码中获得函数引用,也至少需要一次函数调用——一般来说,在性能关键的代码中,这可能不是不可察觉的廉价操作

而且。。。通过提供Test和TestImpl类,CFR重建了与我编译的完全相同的代码


共 (0) 个答案