我们经常需要在 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是一个引用,最后,它将进行引用检查。 -
对于浮点类型
Float和Double,其实现方法equals和compareTo不遵循 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