将通用 Java 回调转换为 Kotlin 时的可空性

Nullability when converting generic Java callback to Kotlin

我正在尝试在 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() })
    }
}

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

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

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

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

我可以这样做:

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

但是我的调用者将无法传递类型为 ()->Int?.

blocks

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

    val helper: MyTransactionHelper = TODO()

    helper.inTransaction {
        if (TODO("some irrelevant condition")) 42 else null
    }
fun <T : Any> inTransaction(block: () -> T?): T? {
    return transactionTemplate.execute(TransactionCallback<T> { block() })
}

: Any绑定可选)。请注意,由于差异,() -> T() -> T? 的子类型,因此用户可以传递 () -> Int(并且仍会返回 Int?)。

然而,

The code doesn't compile. This is because Java class TransactionCallback, defined in Java as...

is interpreted in Kotlin as returning nullable T - T?, but my inTransaction method returns T.

不正确;问题是 TransactionTemplate.execute returning T?,而不是 TransactionCallback.doInTransaction。如果 execute 实际上保证不会 return nullblock 没有(我 认为 从文档中是正确的,但我不确定),然后只需在您的原始代码中添加一个转换:

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