fun checkLengthA(str : String?): Int = if (str.isNullOrBlank()) 0 else str.length
Run Code Online (Sandbox Code Playgroud)
“在 String 类型的可空接收器上只允许安全 (?.) 或非空断言 (!!.) 调用?
所有空对象(或空)都被 isNullOrBlank() 捕获,因此 str.length 中的 str 对象永远不能为空(或空)。这可以通过用显式检查替换扩展函数来实现。
fun checkLengthB(str : String?): Int = if (str == null) 0 else str.length
Run Code Online (Sandbox Code Playgroud)
或不那么冗长的表达:
fun checkLengthC(str : String?): Int = str?.length ?: 0
Run Code Online (Sandbox Code Playgroud)
checkLengthB 和 checkLengthC 都可以正常运行。
让我们从 checkLengthA 中删除可空类型以避免编译错误,如上所示:
fun checkLengthA(str : String): Int = if (str.isNullOrBlank()) 0 else str.length
Run Code Online (Sandbox Code Playgroud)
现在,我们只允许解析使用 String 类型的非空参数,所以如果我们期望一些空类型,那么我们必须把“?” 背部。
看起来编译器不明白在运行 str.length 和扩展函数时,String 类型的 str 永远不会计算为 null,但是如果我们在 if-else 语句中使用 (str == null) ,它将编译没有问题。
谁能解释为什么会这样?
编译器无法证明在isNullOrBlank计算为 之后false,参数不能为空。isNullOrBlank只是一个普通的方法,相同的参数可以应用于任意数量的检查参数是否为空的函数。如果有人改变了isNullOrBlankto always return的实现false怎么办?
在 的情况下arg == null,编译器知道这一定意味着参数不为空,因为这正是== null语法和字面上的意思。
请注意,== null这并不总是导致安全转换,例如,当被检查的变量是一个属性时。
在这种情况下:
str?.length ?: 0
Run Code Online (Sandbox Code Playgroud)
不涉及智能演员表。
str?.length是Int?,使用 Elvis 运算符,?:您最终会得到Int.
有趣的是,实现isNullOrBlank包含这个contract:
contract {
returns(false) implies (this@isNullOrBlank != null)
}
Run Code Online (Sandbox Code Playgroud)
所以也许这会在某个时候得到支持。
| 归档时间: |
|
| 查看次数: |
4438 次 |
| 最近记录: |