【问题标题】:How to pass Kotlin lambda to Java Supplier argument?如何将 Kotlin lambda 传递给 Java 供应商参数?
【发布时间】:2019-09-10 17:14:10
【问题描述】:

我将我的项目迁移到 Kotlin,这个阶段在 Java 和 Kotlin 之间有很多交互。

在下面的示例中,我需要传递一个实现 Java 供应商接口的函数。

java.util.concurrent.CompletableFuture.supplyAsync<Int>({ -> 3 }, executor)

CompletableFuture.supplyAsync({ 3 }, executor)

IntellJ 显示错误:

Type mismatch.
Required: Supplier<Int!>!
Found: () -> Int

我找到了一个使用助手类的解决方法,但它不是内联解决方案。

class Help : Supplier<Int> { fun get() = 3 }
supplyAsync(Help(), executor)

【问题讨论】:

    标签: java kotlin migration


    【解决方案1】:

    这将起作用:

    CompletableFuture.supplyAsync({ 3 }, executor::execute)
    

    注意这两个签名是

    public static <U> supplyAsync(supplier: Supplier<U>, executor: Executor): CompletableFuture<U>
    public static <U> supplyAsync(supplier: () -> U, executor: (Runnable) -> Unit): CompletableFuture<U>
    

    也就是说,如果你想传入一个 lambda,执行它的东西必须是一个方法引用(而不是一个 Executor 实例)。

    编辑:这已记录在 here,Kotlin 允许您调用以适当的 Kotlin 函数作为参数的 SAM(功能接口)参数的方法。然而,这是全部或全部。要么为所有 SAM 参数传递 Kotlin 函数,要么不传递。这解释了为什么您最初采用的方法没有编译。这不是 Java API 的特定方法,而是适用于 Java 类上定义的所有方法。

    【讨论】:

    • 所以基本上你的意思是有一个隐式的第二个签名,它接受 lambdas 而不是 SAM 对象,但是不会有混合和匹配接口和 lambdas 的签名?
    • 这也适用CompletableFuture.supplyAsync(Supplier{ 3 }, executor),我想如果我理解正确的话,这是因为 SAM 构造函数实际上创建了一个实现接口的对象,所以它使用上面的第一个签名。
    • 我更喜欢 Supplier 的解决方案{3},因为它正在调用我想要的方法。绝对 Intellij 应该通过隐式方法的提示来处理这种情况,因为 CompletableFuture 是 Java 类。
    • 是的,Kotlin 以某种方式隐式添加了一些方法,这些方法使 Java 方法接受功能接口,可从 Kotlin 与 lambdas 一起使用。除了 IntelliJ 附带的自动完成功能之外,我不知道这些方法记录的任何地方。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-19
    • 2022-10-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-25
    • 1970-01-01
    相关资源
    最近更新 更多