编译错误:智能转换为“”是不可能的,因为“”是由变化的闭包捕获的局部变量

2024-01-02

为了简化我的实际用例,假设我想找到列表中的最大数字:

var max : Int? = null
listOf(1, 2, 3).forEach {
    if (max == null || it > max) {
        max = it
    }
}

但是,编译失败并出现以下错误:

智能转换为“Int”是不可能的,因为“max”是一个由变化的闭包捕获的局部变量

为什么改变闭包会阻止智能转换在此示例中工作?


一般来说,当在 lambda 函数闭包中捕获可变变量时,智能强制转换不适用于该变量,无论是在 lambda 内部还是在创建 lambda 后的声明范围内。

这是因为该函数可能会脱离其封闭范围,并可能稍后在不同的上下文中执行,可能多次执行,也可能并行执行。作为一个例子,考虑一个假设函数List.forEachInParallel { ... },它为列表中的每个元素执行给定的 lambda 函数,但并行。

编译器必须生成即使在这种严重情况下也能保持正确的代码,因此它不会假设变量的值在空检查后保持不变,因此无法对其进行智能转换。

然而,List.forEach是完全不同的,因为它是一个inline https://kotlinlang.org/docs/reference/inline-functions.html功能。内联函数的主体及其函数参数的主体(除非参数具有noinline or crossinline修饰符)在调用站点内联,因此编译器可以推断作为参数传递给内联函数的 lambda 中的代码,就好像它是直接编写在调用方法主体中一样,从而使智能转换成为可能。

可以,但目前还不行。仅仅是因为该功能尚未实现。有一个悬而未决的问题:KT-7186 https://youtrack.jetbrains.com/issue/KT-7186.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

编译错误:智能转换为“”是不可能的,因为“”是由变化的闭包捕获的局部变量 的相关文章

随机推荐