【问题标题】:How to use equals() and contains() to check nullable type of data? I suppose they are both string's methods, but why they behave differently?如何使用 equals() 和 contains() 检查可空类型的数据?我想它们都是字符串的方法,但是为什么它们的行为不同呢?
【发布时间】:2021-09-07 14:25:19
【问题描述】:

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

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

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

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

【问题讨论】:

  • 任何答案都回答了您的问题吗?如果是这样,请考虑通过单击复选标记接受其中之一:)

标签: kotlin null nullsafe


【解决方案1】:

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:在相等性检查的情况下,你不需要使用equals方法,而可以使用==操作符

【讨论】:

    【解决方案2】:

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

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

    在你的例子中,thisnull,而other 不是null,所以other === null 产生false


    在第二个示例中,myStr.contains("hello") 试图调用名为 contains 的函数,但它不存在,因为您有一个可为空的 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

    【讨论】:

    • 所以实际上,他们都没有使用String 的方法。 ?
    【解决方案3】:

    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 是在不可为空的CharSequence 上声明的。

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

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

    if (myStr?.contains("hello") == true)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-01
      • 2021-02-20
      • 2018-01-05
      • 2015-06-05
      • 2020-12-12
      • 2016-12-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多