这是因为use它是一个内联函数,这意味着 lambda 主体将内联到调用点函数,变量的实际类型myVar取决于其上下文。
如果在myVarlambda 中用于读取,则类型是MyType或其超类型。例如:
// v--- the actual type here is MyType
var myVar: MyType = TODO()
autoClosable.use {
myVar.todo()
}
如果在myVarlambda 中用于写入,则实际类型为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 想要为所有函数保持语义一致。