CompletableFutures回调的奇怪行为

时间:2018-02-12 09:32:51

标签: java completable-future

我想尝试一下CompletableFutures的功能,为此我创建了简单的类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)

当我用新班级替换它时

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的方法参考和apply类的方法Test相同

为什么第一个不起作用?

顺便说一句

为什么这个也是正确的

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

(我将方法姓氏的方法引用传递给thenAcceptthenAccept应该将Consumer作为arg)

1 个答案:

答案 0 :(得分:1)

  

为什么第一个不起作用?

它不起作用,因为 consumer()方法不是静态的;您提供了一个需要静态方法的实例方法。使它成为一个静态方法,您的代码将起作用:

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

BTW为什么这个也是正确的

(即为什么你能成功提供一个方法引用,当所需参数是一个没有返回值的Consumer时返回一个值?)

您的问题与此SO问题重复:Why does a Java method reference with return type match the Consumer interface?

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

以下是此设计决策的基础:Java允许您调用方法并忽略返回值(方法调用表达式作为语句)。由于我们在调用时允许这样做,所以在将方法适用于参数兼容但功能接口无效返回的功能接口时,我们也允许这样做。

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

另见this answer from Holger

...设计决策的基础是允许将方法调整为功能接口,就像调用方法一样,即可以调用每个返回值的方法并忽略返回的值。