【问题标题】:Nullability when converting generic Java callback to Kotlin将通用 Java 回调转换为 Kotlin 时的可空性
【发布时间】:2020-05-03 06:10:36
【问题描述】:

我正在尝试在 Spring 的 TransactionTemplate 上编写 Kotlin 包装器。关键代码如下所示:

import org.springframework.stereotype.Component
import org.springframework.transaction.PlatformTransactionManager
import org.springframework.transaction.support.TransactionCallback
import org.springframework.transaction.support.TransactionTemplate

@Component
class MyTransactionHelper(
    platformTransactionManager: PlatformTransactionManager
) {
    private val transactionTemplate = TransactionTemplate(platformTransactionManager);

    fun <T> inTransaction(block: () -> T): T {
        return transactionTemplate.execute(TransactionCallback<T> { block() })
    }
}

代码无法编译。这是因为Java类TransactionCallback,在Java中定义为:

@FunctionalInterface
public interface TransactionCallback<T> {
    @Nullable
    T doInTransaction(TransactionStatus status);
}

在 Kotlin 中被解释为返回可为空的 T - T?,但我的 inTransaction 方法返回 T

如何更改此代码以使其编译,同时允许我的调用者使用可为空的类型作为泛型类型?

我可以这样做:

fun <T: Any> inTransaction(block: () -> T): T = transactionTemplate.execute { block() }!!

但是我的调用者将无法传递()-&gt;Int? 类型的blocks。

这是我要编译和运行的示例代码:

    val helper: MyTransactionHelper = TODO()

    helper.inTransaction {
        if (TODO("some irrelevant condition")) 42 else null
    }

【问题讨论】:

  • 是否有可能创建一个指定@NonNull 属性的Intermediate 类,然后在Intermediate 类之上创建wrapper

标签: generics kotlin language-interoperability


【解决方案1】:
fun <T : Any> inTransaction(block: () -> T?): T? {
    return transactionTemplate.execute(TransactionCallback<T> { block() })
}

: Any 绑定可选)。请注意,由于方差,() -&gt; T() -&gt; T? 的子类型,因此用户可以传递() -&gt; Int(并且仍然得到Int?)。

然而,

代码无法编译。这是因为Java类TransactionCallback,在Java中定义为...

在 Kotlin 中被解释为返回可为空的 T - T?,但我的 inTransaction 方法返回 T。

不正确;问题是TransactionTemplate.execute 返回T?,而不是TransactionCallback.doInTransaction。如果execute 实际上保证在block 没有返回null 时不会返回(我认为 从文档中是正确的,但不确定),那么只需添加一个演员表您的原始代码:

@Suppress("UNCHECKED_CAST")
fun <T> inTransaction(block: () -> T): T {
    return transactionTemplate.execute(TransactionCallback<T> { block() }) as T
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-09
    • 2018-11-26
    • 1970-01-01
    • 1970-01-01
    • 2020-06-24
    • 1970-01-01
    • 2020-04-18
    • 2018-02-01
    相关资源
    最近更新 更多