对于这段代码,Kotlin迫使我处理无效检查情况,而在另一条线上则没有,尽管情况相同:
if (r1 == null && r2 == null)
throw IllegalArgumentException("All nulls!")
else if (r1 == null)
return r2!!.reading // <----- I am forced to !! here
else if (r2 == null)
return r1.reading // <----- The compiler does not complain in this line
这是一个错误还是一个功能?
答案 0 :(得分:7)
Kotlin编译器没有以你期望的方式做出逻辑推断:“我已经检查过r1 == null和r2 == null,所以现在如果我只检查r1 == null,那么它必须认识到r2不为空“。它没有。你没有在那个分支中检查过r2,所以它没有看到它不是空的。
在第二种情况下,情况更简单:if (r1 == null) { ... } else { ... }
。你在else
内有另一张支票并不重要;编译器发现您在else
检查的if (x == null)
分支中,并且知道该值不为空。
有一个open feature request用于添加这种逻辑,但是,它不在Kotlin团队的近期路线图中。
答案 1 :(得分:2)
恕我直言,如果某些应用程序逻辑是互斥的。我更愿意使用when {}
逐个声明地表达完整条件,而不是使用if(...) else if(..) else
来组成逻辑。
使用when{}
逐个指定完整条件可以帮助开发人员专注于特定情况,这样更容易进行调试和以后的更改。
相比之下,if else
条件迫使开发人员从上到下进行跟踪以获得该部分逻辑的整体概念,这对其他人来说相对难以阅读并且难以指出无法访问的代码。
我遇到了一些复杂的if else
代码,我必须构建一个真值表来理解整个逻辑部分。
回到这个问题。智能案例适用于when{}
:)
实施1
val someReading = when {
r1 != null && r2 == null -> r1.reading
r1 == null && r2 != null -> r2.reading
else -> throw IllegalArgumentException("All nulls!")
}
实施2
val someReading =
r1?.reading
?: r2?.reading
?: throw IllegalArgumentException("All nulls!")
答案 2 :(得分:1)
您可以稍微重新构建if
表达式,这样可以减少检查次数并将智能广播应用于r2
:
if (r1 == null) {
if (r2 == null) throw IllegalArgumentException("All nulls!")
return r2.reading
} else if (r2 == null) {
return r1.reading
}