为了简化我的实际用例,我们假设我想在列表中找到最大数量:
var max : Int? = null
listOf(1, 2, 3).forEach {
if (max == null || it > max) {
max = it
}
}
Run Code Online (Sandbox Code Playgroud)
但是,编译失败,并出现以下错误:
智能转换为'Int'是不可能的,因为'max'是一个由变化的闭包捕获的局部变量
为什么更改闭包会阻止智能演员在此示例中工作?
Ily*_*lya 18
通常情况下,当在lambda函数闭包中捕获可变变量时,智能强制转换不适用于lambda内部和声明范围创建lambda之后的变量.
这是因为函数可以从其封闭范围中逃脱,并且可以稍后在不同的上下文中执行,可能多次并且可能并行执行.例如,考虑一个假设函数List.forEachInParallel { ... }
,它为列表的每个元素执行给定的lambda函数,但是并行执行.
编译器必须生成即使在那种严重情况下仍然保持正确的代码,因此它不会假设变量的值在空检查后保持不变,因此无法智能地转换它.
但是List.forEach
有点不同,因为它是一种inline
功能.内联函数的主体及其功能参数的主体(除非参数有noinline
或crossinline
修饰符)在调用站点内联,因此编译器可以推断作为内联函数的参数传递的lambda中的代码,就像它被写入一样直接在调用方法体中使智能投射成为可能.
它可以,但目前它没有,只是因为该功能尚未实现.有一个未解决的问题:KT-7186.
感谢Ilya对问题的详细解释!您可以for(item in list){...}
像这样使用标准表达式:
var max : Int? = null
val list = listOf(1, 2, 3)
for(item in list){
if (max == null || item > max) {
max = item
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
4596 次 |
最近记录: |