Kotlin:无法一次应用两个条件,检查 "return body" 函数样式

Kotlin: Cannot apply two conditionals at once check with "return body" function style

我有一个像这样的简单功能检查:

    fun parseValidBluetoothBrickedId(controllerId: String?): Boolean{
    if(controllerId != null){
        if(controllerId.startsWith(BLUETOOTH_NAME_PREFIX) && controllerId.length > BLUETOOTH_NAME_PREFIX.length)
            return true
    }

    return false
}

我想将其转换为更简单的样式:

   fun parseValidBluetoothBrickedId(controllerId: String?) =
        controllerId?.length > BLUETOOTH_NAME_PREFIX.length
      &&  controllerId?.startsWith(BLUETOOTH_NAME_PREFIX)

但是 IDE(Android Studio 3.0 Beta7) 给我一个错误,强调大于 ('>') 运算符:

Operator calls corresponds to a dot-qualified call 'controllerId?.length.compareTo(BLUETOOTH_NAME_PREFIX.length) which is not allowed here

它还强调了错误行 controllerId?.startsWith(BLUETOOTH_NAME_PREFIX) 并说:

Type mismatch. Required: Boolean, Found Boolean?

真的有什么问题吗?这只是一个简单的方法,适用于第一个块 if-else 样式。

您的转换函数缺少 null 检查:

fun parseValidBluetoothBrickedId(controllerId: String?) =
        controllerId != null && controllerId.length > "".length
                && controllerId.startsWith("")

如在您的第一个示例中,编译器必须进行空检查才能知道 controllerId 不是 null。检查后,编译器使用 "smart casting" 并且调用是安全的。 因此,您不必在检查后使用 ?. 符号。

当您执行 controllerId?.length 时,您将获得 Int?。您不能将 IntInt? 进行比较。这就是您遇到第一个错误的原因。

你得到另一个错误是因为 controllerId?.startsWith(BLUETOOTH_NAME_PREFIX) returns Boolean?。不能对可为 null 的参数使用 && 运算符。它需要两个 Boolean.

类型的参数

要解决问题,您需要先检查controllerId != null。这会将 controllerId 智能转换为不可空类型 String。像这样:

fun parseValidBluetoothBrickedId(controllerId: String?): Boolean =
    controllerId != null
        && controllerId.startsWith(BLUETOOTH_NAME_PREFIX)
        && controllerId.length > BLUETOOTH_NAME_PREFIX.length

您不能在 controllerId?.length 上调用 compareTo(使用 < 运算符),因为它的类型是 Int?,这意味着它可能是 null, 在这种情况下它不能作为数字进行比较。

类似地,controllerId?.startsWith(BLUETOOTH_NAME_PREFIX) 调用 returns Boolean?(因为如果 controllerId 是 [=15=,它将 return null ]), 不能传递给 && 运算符,只有真正的 Boolean 可以。

这里的解决方案是 null 检查你在原来的方法中所做的,并通过智能转换将你的 controllerId 转换为 [=25 来摆脱安全调用=]:

fun parseValidBluetoothBrickedId(controllerId: String?): Boolean =
        controllerId != null 
        &&  controllerId.length > BLUETOOTH_NAME_PREFIX.length
        &&  controllerId.startsWith(BLUETOOTH_NAME_PREFIX)