CompletableFutures 奇怪的回调行为

CompletableFutures strange behavior with callbacks

我想试验 CompletableFutures 的能力,为此我创建了简单的 class CompletableFutureTests

这是我的方法:

private static String name() {
    System.out.println("Name");
    return "ALmas";
}

@SneakyThrows(InterruptedException.class)
private static String surname(String name) {
    Thread.sleep(2000);
    System.out.println("sur");
    return name+" Abdrazak";
}

private static String world(String name) {
    System.out.println("world");
    return name + " hello";
}

private void consumer(String str){
    System.out.println("str");
}

private static String onExc(Exception name) {
    return "on exception";
}

和用法

CompletableFuture.supplyAsync(CompletableFutureTests::name)
                         .thenApplyAsync(CompletableFutureTests::surname)
                         .thenApply(CompletableFutureTests::world)
                         .thenAccept(CompletableFutureTests::consumer);

这段代码把我扔了

RuntimeException: Uncompilable source code - Erroneous sym type: java.util.concurrent.CompletableFuture.thenAccept

由于这条线

.thenAccept(CompletableFutureTests::consumer)

当我用新的替换它时 class

private static class Test implements Consumer<String>{

        @Override
        public void accept(String t) {
           System.out.println(t);
        }
        }

    }

CompletableFuture.supplyAsync(CompletableFutureTests::name)
                             .thenApplyAsync(CompletableFutureTests::surname)
                             .thenApply(CompletableFutureTests::world)
                             .thenAccept(new Test());

它按方面工作。如您所见,对方法 consumer 的方法引用和 Test class 对方法 apply 的引用是相同的

为什么第一个不起作用?

顺便说一句

为什么这个也是正确的

CompletableFuture.supplyAsync(CompletableFutureTests::name)
                             .thenApplyAsync(CompletableFutureTests::surname)
                             .thenApply(CompletableFutureTests::world)
                             .thenAccept(CompletableFutureTests::surname);

(我将方法引用传递给 thenAcceptthenAccept 应该将 Consumer 作为参数)

Why first one doesn't work?

它不起作用,因为您的 consumer() 方法不是静态的;您正在提供需要静态方法的实例方法。将其设为静态方法,您的代码即可运行:

private static void consumer(String str) {
    System.out.println("str");
}

BTW Why this one is also correct

(即,当所需参数是没有 return 值的消费者时,为什么您可以成功提供一个 return 值的方法引用?)

您的问题与此 SO 问题重复:

特别注意来自 Brian Goetz 的这些评论:

此设计决策的基础如下:Java 允许您调用方法并忽略 return 值(作为语句的方法调用表达式)。由于我们在调用时允许这样做,因此在将方法适配为参数兼容但功能接口为 void-returning.

的功能接口时,我们也允许这样做

另请注意,我们将进行其他调整(装箱、拆箱)以使 lambda 的形状与功能界面的预期形状相匹配。忽略 return 值只是其中一种调整。

另见 :

...设计决策的基础是允许以与调用方法相同的方式将方法适配到功能接口,即您可以调用每个值 returning方法并忽略 returned 值。