在处理不可变变量和属性时,将Kotlin null安全运算符链接起来是否是一种不好的做法?

在处理不可变变量和属性时,将Kotlin null安全运算符链接起来是否是一种不好的做法?,kotlin,kotlin-null-safety,Kotlin,Kotlin Null Safety,以下面假设的伪代码为例: val a: Any? = ... a?.takeIf { ... } ?.apply { ... } ?.let { ... } 我最近读过一篇文章,文章指出这种空安全操作符的使用在编译成Java机器代码时会产生冗余的空检查。在这里——根据那篇文章——似乎在编译时,a!=null的计算结果为true它将检查a!=null对同一变量执行三次。当您处理可能在检查之间更改值的var属性时,这可能会导致错误。但在具有不可变的val属性的情况下,这会创建冗余检

以下面假设的伪代码为例:

val a: Any? = ...
a?.takeIf { ... }
    ?.apply { ... }
    ?.let { ... }
我最近读过一篇文章,文章指出这种空安全操作符的使用在编译成Java机器代码时会产生冗余的空检查。在这里——根据那篇文章——似乎在编译时,
a!=null
的计算结果为
true
它将检查
a!=null
对同一变量执行三次。当您处理可能在检查之间更改值的
var
属性时,这可能会导致错误。但在具有不可变的
val
属性的情况下,这会创建冗余检查。如果在可枚举数据结构上对每个元素执行上述示例,这将线性扩展冗余检查,从而使最终结果的计算复杂度增加3倍

从语法上讲,以这种方式使用Kotlin很有意义。但是,如果它产生这样的浪费/冗余检查,那么最好通过使用
if
语句显式地空检查变量来避免这种情况


空安全运算符的链式用法是否合适,尤其是与lambda结合使用时,它会多次检查同一个不可变变量?或者换句话说,这样做真的会导致编译后的java机器代码中出现过多/冗余的空检查吗?

从性能角度看,这在绝大多数情况下都是无关紧要的。也许是在10000个项目的循环中,你可能开始担心优化的水平。您应该更关心的是代码的清晰性。这种级别的链接,不是为了提供默认值,而是为了执行一系列操作,既丑陋又难以遵循。在上面的例子中,
?。
takeIf
之前是不必要的,而
apply
中的任何代码都可以放在
let
语句中。实际上没有过多的空检查。JIT将消除任何在运行时被证明是不必要的。这一点不值得关注。@Tenfour04这是一个很好的观点,尽管该代码更多的是作为一个假设的情况,而不是一个现实的例子。我想问题是,您可能并不总是知道循环的枚举的大小,以便知道如何针对这种情况进行优化。虽然在这一点上,可能会有比一些空检查更大的优化问题。从性能角度看,在绝大多数情况下,这是无关紧要的。也许是在10000个项目的循环中,你可能开始担心优化的水平。您应该更关心的是代码的清晰性。这种级别的链接,不是为了提供默认值,而是为了执行一系列操作,既丑陋又难以遵循。在上面的例子中,
?。
takeIf
之前是不必要的,而
apply
中的任何代码都可以放在
let
语句中。实际上没有过多的空检查。JIT将消除任何在运行时被证明是不必要的。这一点不值得关注。@Tenfour04这是一个很好的观点,尽管该代码更多的是作为一个假设的情况,而不是一个现实的例子。我想问题是,您可能并不总是知道循环的枚举的大小,以便知道如何针对这种情况进行优化。不过,在这一点上,可能会有比一些空检查更大的优化问题。