这是因为use
它是一个内联函数,这意味着 lambda 主体将内联到调用点函数,变量的实际类型myVar
取决于其上下文。
如果在myVar
lambda 中用于读取,则类型是MyType
或其超类型。例如:
// v--- the actual type here is MyType
var myVar: MyType = TODO()
autoClosable.use {
myVar.todo()
}
如果在myVar
lambda 中用于写入,则实际类型为ObjectRef
. 为什么?这是因为 Java 不允许您将变量更改出令人讨厌的类范围。实际上,myVar
是有效的-final。例如:
// v--- the actual type here is an ObjectRef type.
var myVar: MyType
autoClosable.use {
myVar = autoClosable.foo()
}
因此,当编译器检查 时println(myVar)
,它不能确定 的元素是否ObjectRef
已初始化。然后引发编译器错误。
如果你捕捉到任何东西,代码也无法编译,例如:
// v--- the actual type here is an ObjectRef type.
var myVar: MyType
try {
autoClosable.use {
myVar = it.foo()
}
} catch(e: Throwable) {
myVar = MyType()
}
// v--- Error: Variable 'myVar' must be initialized
println(myVar)
但是当实际类型myVar
是时MyType
,它工作正常。例如:
var myVar: MyType
try {
TODO()
} catch(e: Throwable) {
myVar = MyType()
}
println(myVar) // works fine
为什么kotlin 没有优化内联函数以MyType
直接用于编写?
我唯一认为,编译器不知道myVar
将来是否在另一个内联函数的 lambda 主体中使用。或者 kotlin 想要为所有函数保持语义一致。