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

时间:2019-06-12 09:27:11

标签: java spring spring-boot kotlin

当试图创建一个简单的数据库助手时,我有一个来自Spring的RowMapper<T>我想填写,但是Kotlin坚持使用KFunction2,即使RowMapper的界面也是如此。火柴。这适用于Spring Java代码中的原始接口。

在我看来,方法在重要部分上具有相同的含义。但是,科特林不同意我的看法。

我的界面(kotlin)如下:

interface MyJdbcOperations : NamedParameterJdbcOperations {
    fun <T> querySingle(
        sql: String,
        parameters: MapSqlParameterSource,
        rowMapper: RowMapper<T>): Optional<T>
}

NamedParameterJdbcOperations内部的查询界面如下所示(Java):

public interface NamedParameterJdbcOperations {
    // ... rest of interface omitted for readability

    <T> List<T> query(String sql, SqlParameterSource paramSource, RowMapper<T> rowMapper)
            throws DataAccessException;
}

但是当我按如下方式使用MyJdbcOperations的实现时:

template.query<Foo>(sql, parameters, this::mapToFoo)
template.querySingle<Foo>(sql, parameters, this::mapToFoo)

第一个版本有效,没问题,我也可以删除<Foo>并让类型推断来完成它的工作。

第二个版本却给我类似以下错误:

Error:(25, 54) Kotlin: Type mismatch: inferred type is KFunction2<@ParameterName ResultSet, @ParameterName Int, Foo> but RowMapper<Foo> was expected

但是我实际上希望这能正常工作,如果KFunction2签名在Java接口中可以满足RowMapper<Foo>,那么我当然希望它在Kotlin中也能够。显然不是这样。

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

2 个答案:

答案 0 :(得分:3)

我看到的工作情况与带有编译错误的调用之间的主要区别在于,第二个引用了Kotlin接口中定义的方法,而第一个引用了Java接口中定义的方法。

我知道SAM转换仅从lambas /方法转换为Java接口,如此处所述:https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions。 我不知道为什么这会影响您的情况,但是如果您将MyJJdbcOperations重新定义为Java接口,问题就会消失...

这不是真正的解决方案,但这是一种解决方法。

似乎lambdas(我也尝试过{x -> this.mapToFoo(x)}之类的labdas,已经遇到了相同的结果)和传递给Kotlin接口方法的方法都转换为KFunctionN而不是预期的接口,当预期的接口被定义为Java接口时...

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

答案 1 :(得分:1)

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

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

感谢@ pietro-martinelli发布了一个答案,帮助我走了正确的路:)