Java Lambda表达式在看似相同的kotlin中不起作用

Java Lambda表达式在看似相同的kotlin中不起作用,java,spring,spring-boot,kotlin,Java,Spring,Spring Boot,Kotlin,当尝试创建一个简单的数据库帮助程序时,我有一个来自Spring的RowMapper,我想填写它,但是Kotlin坚持使用KFunction2,即使RowMapper的接口匹配。这适用于SpringJava代码中的原始接口 在我看来,这些方法在重要的部分是相同的。然而,科特林并不同意我的观点 我的界面kotlin如下所示: interface MyJdbcOperations : NamedParameterJdbcOperations { fun <T> querySingl

当尝试创建一个简单的数据库帮助程序时,我有一个来自Spring的RowMapper,我想填写它,但是Kotlin坚持使用KFunction2,即使RowMapper的接口匹配。这适用于SpringJava代码中的原始接口

在我看来,这些方法在重要的部分是相同的。然而,科特林并不同意我的观点

我的界面kotlin如下所示:

interface MyJdbcOperations : NamedParameterJdbcOperations {
    fun <T> querySingle(
        sql: String,
        parameters: MapSqlParameterSource,
        rowMapper: RowMapper<T>): Optional<T>
}
template.query<Foo>(sql, parameters, this::mapToFoo)
template.querySingle<Foo>(sql, parameters, this::mapToFoo)
但当我使用MyJDBC操作的实现时,如下所示:

interface MyJdbcOperations : NamedParameterJdbcOperations {
    fun <T> querySingle(
        sql: String,
        parameters: MapSqlParameterSource,
        rowMapper: RowMapper<T>): Optional<T>
}
template.query<Foo>(sql, parameters, this::mapToFoo)
template.querySingle<Foo>(sql, parameters, this::mapToFoo)
第一个版本可以工作,没有问题,我也可以删除并让类型推断完成它的工作

但是,第二个版本给了我以下错误:

Error:(25, 54) Kotlin: Type mismatch: inferred type is KFunction2<@ParameterName ResultSet, @ParameterName Int, Foo> but RowMapper<Foo> was expected
然而,我实际上认为这是可行的,如果KFunction2签名能够在Java接口中满足RowMapper,那么我最肯定的是它在Kotlin中也能够满足。情况显然并非如此


那么我做错了什么,最好的解决方法是什么呢?

我看到的工作案例和带有编译错误的调用之间的关键区别是,第二个引用在Kotlin接口中定义的方法,而第一个使用在Java接口中定义的方法

我知道SAM转换仅从lambas/方法到Java接口,如下所述:。 我不明白为什么这会影响您的场景,但是如果您将MyJJdbcOperations重新定义为Java接口,问题就会消失

这不是一个真正的解决方案,但它是一个变通办法

似乎我也尝试过类似于{x->this.maptoox}的labdas,结果与您已经遇到的结果相同,传递给Kotlin接口方法的方法被转换为KFunction,而不是预期的接口,同样当预期的接口被定义为Java接口时


这不是一个完整的答案,但我希望这可以帮助您更接近解决方案。

我看到的工作案例和带有编译错误的调用之间的关键区别是,第二个引用在Kotlin接口中定义的方法,而第一个使用在Java接口中定义的方法

我知道SAM转换仅从lambas/方法到Java接口,如下所述:。 我不明白为什么这会影响您的场景,但是如果您将MyJJdbcOperations重新定义为Java接口,问题就会消失

这不是一个真正的解决方案,但它是一个变通办法

似乎我也尝试过类似于{x->this.maptoox}的labdas,结果与您已经遇到的结果相同,传递给Kotlin接口方法的方法被转换为KFunction,而不是预期的接口,同样当预期的接口被定义为Java接口时


这不是一个完整的答案,但我希望这能帮助您更接近解决方案。

我找到了至少一个解决方法,但我仍然对为什么会发生这种情况以及为什么它不能按预期工作感到困惑。以下将解决当前的问题:

    template.querySingle<Foo>(sql, parameters, RowMapper { rs, rowNum -> this.mapToFoo(rs, rowNum) })

感谢@pietro martinelli发布了一个帮助我找到正确道路的答案:

我至少找到了一个解决办法,但我仍然对为什么会发生这种情况以及为什么它没有按预期工作感到困惑。以下将解决当前的问题:

    template.querySingle<Foo>(sql, parameters, RowMapper { rs, rowNum -> this.mapToFoo(rs, rowNum) })

感谢@pietro martinelli发布了一个帮助我找到正确道路的答案:

为什么这个答案不完整?它完美地解释了这一点。也许正确的方法是不使用RowMapper作为参数类型,而是使用kotlin接口中的RowMapper:rs:ResultSet,rowNum:int->T作为最后一个参数类型?来自您链接的同一来源:还要注意,此功能仅适用于Java互操作;由于Kotlin具有适当的函数类型,因此不需要将函数自动转换为Kotlin接口的实现,因此unsupported@sfiss我倾向于同意,它确实相当完整:我认为唯一缺少的部分实际上是他的答案让我得到的补充:使用我认为使用RowMapper确实是正确的做法。首先,它传达了特定的意图和上下文。我想知道的是:有没有办法给一个合适的函数类型命名并记录它们?如果不是的话,我倾向于争辩说,他们声称这是不必要的可能是错误的,也许是一个类型别名?Ofc,RowMapper typealias将与spring的RowMapper不同。@sfiss哦,谢谢我一直在寻找:是的,肯定比没有好,但不完全一样:为什么这个答案不完整?它完美地解释了这一点。也许正确的方法是不使用RowMapper作为参数类型,而是使用kotlin接口中的RowMapper:rs:ResultSet,rowNum:int->T作为最后一个参数类型?来自您链接的同一来源:还要注意,此功能仅适用于Java互操作;由于Kotlin具有适当的函数类型,因此可以将函数自动转换为Kotlin的实现
接口是不必要的,因此unsupported@sfiss我倾向于同意,它确实是相当完整的:我认为唯一缺少的部分实际上是他的答案引导我添加的内容:使用我认为使用RowMapper确实是正确的做法。首先,它传达了特定的意图和上下文。我想知道的是:有没有办法给一个合适的函数类型命名并记录它们?如果不是的话,我倾向于争辩说,他们声称这是不必要的可能是错误的,也许是一个类型别名?Ofc,RowMapper typealias将与spring的RowMapper不同。@sfiss哦,谢谢,我一直在寻找:是的,肯定比没有好,但不完全一样: