为什么我被迫使用! 在空检查的组合?
对于这段代码,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
这是一个错误还是一个function?
Kotlin编译器不会按照您期望的方式进行逻辑推理:“我已经检查过r1 == null和r2 == null,所以现在如果我只检查r1 == null,那么它必须认识到r2不为空“。 它不。 你没有在该分支中检查r2,所以没有看到它不是空的。
在第二种情况下情况更简单: if (r1 == null) { ... } else { ... }
。 不要紧,你有另一个检查else
内部; 编译器发现你在if (x == null)
检查的else
分支中,并且知道这个值不是null。
有一个公开的function要求 ,增加这种逻辑,但是,这不是在Kotlin团队的近期路线图。
恕我直言,如果一些应用程序逻辑是相互排斥的。 我宁愿使用when {}
来声明性地expression全部情况,而不是使用if(...) else if(..) else
来组成逻辑。
使用when{}
指定全部条件时,可以帮助开发人员只关注特定的情况,这对于调试和稍后的更改更加容易。
相反, 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!")
你可以稍微重构你的if
expression式,所以它会减少检查,并将smart-cast应用到r2
:
if (r1 == null) { if (r2 == null) throw IllegalArgumentException("All nulls!") return r2.reading } else if (r2 == null) { return r1.reading }