4

案例一:可以编译运行。为什么 null 调用 equals() 时没有异常?

var myStr:String? = null
if (myStr.equals("hello"))  
    println("equals hello")
else
    println("not equals hello")

案例2:它无法编译。我想它类似于上述情况,但我错了。为什么?

var myStr:String? = null
if (myStr.contains("hello"))
    println("contains hello")
else
    println("not contains hello")
4

3 回答 3

2

equals函数被定义为可空字符串引用上的扩展函数String?,而contains方法被定义在非可空字符串上CharSequence

public actual fun String?.equals(other: String?, ignoreCase: Boolean = false): Boolean = ...


public operator fun CharSequence.contains(other: CharSequence, ignoreCase: Boolean = false): Boolean = ...

在这两种情况下myStr都是可以为空的字符串,所以你不能contains直接调用。您可以使用空安全运算符?.进行调用contains

if(myStr?.contains("hello") == true)
    println("contains hello")
else
    println("not contains hello")

PS:等式检查时,不需要使用equalsmethod,直接使用==operator即可

于 2021-06-24T05:11:49.517 回答
2

equals在可空字符串上有效,只是因为它是一种非常特殊的情况。有一个equals专门为String?.

fun String?.equals(
    other: String?, 
    ignoreCase: Boolean = false
): Boolean

这不适Int?用于 ,例如:

var i: Int? = null
if (i.equals(1)) // error here
    println("equals 1")
else
    println("not equals 1")

equals函数是为 而Any不是声明的Any?,因此通常不能在可为空的类型上调用

无论如何,比较相等性的惯用方法是使用a == b,它转换a?.equals(b) ?: (b === null)为可空的a

也没有理由允许myStr.contains("hello")编译,因为contains在 non-nullable 上声明了CharSequence

operator fun CharSequence.contains(
    other: CharSequence, 
    ignoreCase: Boolean = false
): Boolean

您可以使用可空链接来检查它:

if (myStr?.contains("hello") == true)
于 2021-06-24T05:17:05.590 回答
2

在第一个示例中,myStr.equals调用String?.equals扩展函数,该函数执行以下操作:

if (this === null)
    return other === null

在您的情况下,thisisnullotheris not null,所以other === null产生false


在第二个示例中,myStr.contains("hello")试图调用一个名为 的函数contains,但它不存在,因为您有一个 nullable String?,并且没有contains为该类型定义函数。有该CharSequence.contains功能,但仅针对不可为空的类型定义。

因此,由于该函数不存在,您会收到编译器错误。


通常,您无论如何都不需要使用该equals功能,并且应该更喜欢==运算符:

val myStr:String? = null
if (myStr == "hello")
    println("equals hello")
else
    println("not equals hello")

对于包含,可以先使用?.运算符确保左边的对象不为空:

val myStr:String? = null
if (myStr?.contains("hello") == true)
    println("contains hello")
else
    println("not contains hello")

在这里,myStr?.contains("hello")产生null,并且null == truefalse,所以结果是false

于 2021-06-24T05:20:09.363 回答