仅在类型字符串的无效接收器上允许使用安全(.)或非毫无疑问的(!.)调用


fun checkLengthA(str : String?): Int = if (str.isNullOrBlank()) 0 else str.length

"仅安全(?。(或非障碍(!!(允许在类型字符串的无效接收器上进行调用?

所有null对象(或空(均被isNullorBlank((捕获,因此str.length中的str对象永远不可能为null(或空(。这可以通过用显式检查替换扩展功能来实现。

fun checkLengthB(str : String?): Int = if (str == null) 0 else str.length

或更少的详细表达式:

fun checkLengthC(str : String?): Int = str?.length ?: 0

CheckLengthB和CheckLength C都将在没有问题的情况下运行。

让我们从CheckLengthA中删除可无效的类型以避免编译错误,上面突出显示:

fun checkLengthA(str : String): Int = if (str.isNullOrBlank()) 0 else str.length

现在,我们只允许我们使用类型字符串的非编号参数,因此,如果我们期望某些空类型,那么我们必须放置"?"返回。

看来Crumplier不了解类型字符串的str在运行str.length和扩展功能时永远不会评估为null,但是如果我们在if-else中使用(str == null(,它将在没有问题的情况下进行编译语句。

谁能解释为什么会发生?

编译器无法证明isNullOrBlankfalse评估后,该参数不得无效。isNullOrBlank只是一种普通方法,相同的参数可以应用于检查参数是否为null的任意数量的函数。如果有人将isNullOrBlank的实现更改为始终返回false

arg == null的情况下,编译器知道这一定意味着该参数不是零,因为这正是 == null的含义,在语法上是句法。

请注意,== null并不总是会导致安全的铸件,例如,当被检查的变量是属性时。

在这种情况下:

str?.length ?: 0

不涉及智能演员。

str?.lengthInt?,使用猫王操作员?:您最终将使用Int


有趣的是,isNullOrBlank的实现包含此contract

contract {
    returns(false) implies (this@isNullOrBlank != null)
}

所以也许这将在某个时候得到支持。

最新更新