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