我们经常需要在 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 浮点运算标准 (参见:官方文档介绍)
所以虽然 ==
和 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