将通用 Java 回调转换为 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() })
}
}

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

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

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

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

我可以做这样的事情:

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

但是我的呼叫者将无法传递block类型()->Int?

下面是一个示例代码,我想编译并运行它:

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?(。

然而

代码无法编译。这是因为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
}

最新更新