ITmob-Ly
发布于 2022-08-29 / 377 阅读
0

Kotlin 中的相等判断(==、=== 和 equals)

我们经常需要在 Kotlin 中比较两个变量或对象的数据或者两个对象的引用。这就带来了一个问题,我们应该使用哪种方式判断相等?

如官方文档中所说,在 Kotlin 中有两种类型的相等:

  • 结构相等 (== - 检查 equals() )
  • 引用相等 (=== - 判断两个引用是否指向同一个对象)

结构相等

结构相等使用 == 操作符, 以及它的相反操作符 !=, 来判断。按照约定, a == b 这样的表达式将被转换为:

a?.equals(b) ?: (b === null)

如果 a 不为 null, 将会调用 equals(Any?) 函数, 否则(如果 a 为 null) 将会检查 b 是否指向 null.

注意, 当明确地与 null 进行比较时, 没有必要优化代码: a == null 将会自动转换为 a === null

如果需要实现自定义的相等判断, 请覆盖 [equals(other: Any?): Boolean](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-any/equals.html) 函数。同名但参数不同的其他函数, 比如 equals(other: Foo), 不会影响到使用操作符 == 和 != 进行的相等判断。

结构相等与 Comparable<...> 接口定义的比较操作没有关系, 因此, 只有 equals(Any?) 函数的自定义实现才会影响相等操作符的结果。

引用相等

引用相等使用 === 操作符, 以及它的相反操作 !== 。当且仅当, a 与b 指向同一个对象时, a === b 结果为 true. 对于运行时期表达为基本类型的那些值(比如, Int), === 判断等价于 == 判断.

浮点数值的相等比较

如果相等比较的对象值类型可以静态地判定为 Float 或 Double (无论可否为 null), 那么相等判断将使用 IEEE 754 浮点数运算标准.

否则, 将会使用结构相等判定, 这种判定不遵循 IEEE 754 浮点数运算标准, 因此 NaN 等于它自己, 而且 -0.0 不等于 0.0.

以上是官方文档对相等判断的介绍


总结

  • Java 相同,Any.equals() 函数比较的是两个对象的引用是否相等。也就是说,如果没有覆盖 equals() 函数,== 与 === 的结果是相同的。

  • 如果比较的是基本数据类型 === 等价于 ==

  • 当明确地比较 null 时,优化代码是没有意义。 a == null 将自动转换为 a === null 因为 null 是一个引用,最后,它将进行引用检查。

  • 对于浮点类型 FloatDouble,其实现方法 equalscompareTo 不遵循 IEEE 754 浮点运算标准 (参见:官方文档介绍

    • NaN 会被判定为等于它自己

    • NaN 会被判定为大于任何其他数值, 包括正无穷大(POSITIVE_INFINITY)

    • -0.0 会被判定为小于 0.0

    所以虽然 ==equals() 等价,但很多情况下使用的是 ==

    fun main() {
        val c:Float = 0f
        val a:Float = -0f
        println("${a==b}")           // true
        println("${a.equals(b)}")    // false
    }
    

Kotlin 和 Java 中相等判断的区别,参加另一篇文章:
https://itmob.cn/archives/equality-in-kotlin-and-java