为什么这会出现编译错误?
val autoClosable = MyAutoClosable()
var myVar: MyType
autoClosable.use {
myVar= it.foo()
}
println(myVar) // Error: Variable 'myVar' must be initialized
也许编译器只是看到{ myVar= it.foo() }
作为传递给另一个函数并且不知道何时或是否会执行的函数?
但是由于use
不仅仅是一个函数,而是 Kotlin 替代 Java 的 try-with-resource,了解一些关于它的特殊知识是合适的,不是吗?现在,我被迫初始化myVar
带有一些虚拟值,这根本不符合 Kotlin 的精神。
Since use { ... }
不是一种语言结构,而是只是一个库函数 https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/use.html,编译器不知道(并且目前不努力证明)您传递的 lambda 是曾经被处决。因此,禁止使用可能未初始化的变量。
例如,将您的代码与此函数调用进行比较。无需额外的代码分析,它们对于编译器来说是相同的:
inline fun ignoreBlock(block: () -> Unit) = Unit
var myVar: MyType
ignoreBlock { myVar = it.foo() }
println(myVar) // Expectedly, `myVar` stays uninitialized, and the compiler prohibits it
要绕过此限制,您可以使用从返回的值use
(这是您的块返回的值)来初始化您的变量:
val myVar = autoClosable.use {
it.foo()
}
如果您还想处理它可能抛出的异常,那么使用try作为一个表达 https://kotlinlang.org/docs/reference/exceptions.html#try-is-an-expression:
val myVar = try {
autoClosable.use {
it.foo()
}
} catch (e: SomeException) {
otherValue
}
理论上,内联函数实际上可以被检查以调用 lambda 一次,如果 Kotlin 编译器可以做到这一点,它将允许您的用例和其他一些用例。但这尚未实施。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)