将通用 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?
.
的 block
s
这是我要编译的示例代码 运行:
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 null
而 block
没有(我 认为 从文档中是正确的,但我不确定),然后只需在您的原始代码中添加一个转换:
@Suppress("UNCHECKED_CAST")
fun <T> inTransaction(block: () -> T): T {
return transactionTemplate.execute(TransactionCallback<T> { block() }) as T
}
我正在尝试在 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?
.
block
s
这是我要编译的示例代码 运行:
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 null
而 block
没有(我 认为 从文档中是正确的,但我不确定),然后只需在您的原始代码中添加一个转换:
@Suppress("UNCHECKED_CAST")
fun <T> inTransaction(block: () -> T): T {
return transactionTemplate.execute(TransactionCallback<T> { block() }) as T
}