1. 概述
在 Kotlin 中,我们经常需要比较两个对象是否相等。Kotlin 提供了两个不同的运算符:==
和 ===
,分别代表结构相等(Structural Equality)和引用相等(Referential Equality)。
这两个概念在 Java 中也有对应的体现:==
用于比较基本类型值或对象引用,而 equals()
方法用于结构比较。但在 Kotlin 中语法更加清晰,也更不容易出错。
2. 引用相等(===)
使用 ===
运算符时,Kotlin 会比较两个对象的引用地址,即它们是否指向堆内存中的同一个对象。
这相当于 Java 中的 ==
比较对象引用的行为。
示例:
val a = Integer(10)
val b = Integer(10)
println(a === b) // false
虽然 a
和 b
的值都是 10,但它们是两个不同的 Integer
实例,因此引用不同,===
返回 false
。
✅ 踩坑提醒:不要误以为 ===
是比较值,它只比较引用。
3. 结构相等(==)
使用 ==
运算符时,Kotlin 会调用对象的 equals()
方法进行比较,即比较两个对象的内容是否一致。
这相当于 Java 中的 equals()
方法。
示例:
val a = Integer(10)
val b = Integer(10)
println(a == b) // true
此时 ==
会调用 Integer.equals()
,判断值是否相同,所以返回 true
。
✅ 提示:如果你自定义了类,想要 ==
正常工作,记得重写 equals()
和 hashCode()
方法。
4. 复杂对象的比较
对于自定义的复杂对象,==
和 ===
的行为也是一致的:
===
比较引用==
比较内容(通过equals()
)
示例:
data class User(val name: String, val age: Int, val hobbies: List<String>)
val user1 = User("Alice", 25, listOf("Reading", "Hiking"))
val user2 = User("Alice", 25, listOf("Reading", "Hiking"))
println(user1 == user2) // true
println(user1 === user2) // false
==
返回true
是因为data class
自动生成了equals()
方法,能递归比较内部字段,包括List<String>
。===
返回false
是因为user1
和user2
是两个不同的对象实例。
⚠️ 注意:如果是普通类(非 data class),必须手动实现 equals()
才能让 ==
正常工作。
5. 数组的结构相等
在 Kotlin 中,数组的结构比较不能直接使用 ==
,因为数组类型没有重写 equals()
方法。Kotlin 提供了两个扩展函数用于数组比较:
contentEquals()
:用于一维数组比较contentDeepEquals()
:用于多维数组比较
示例:
val arr1 = arrayOf("Hiking", "Chess")
val arr2 = arrayOf("Hiking", "Chess")
println(arr1 contentEquals arr2) // true
如果使用 ==
,结果会是 false
,因为 arr1
和 arr2
是两个不同的数组对象。
✅ 建议:在比较数组内容时,务必使用 contentEquals
或 contentDeepEquals
。
6. 总结
运算符 | 含义 | 对应 Java 行为 | 说明 |
---|---|---|---|
== |
结构相等 | equals() |
比较对象内容 |
=== |
引用相等 | == (对象) |
比较对象引用 |
- 对基本类型(如
Int
、String
)来说,==
和===
效果一样(因为自动装箱缓存)。 - 对对象来说,要根据需求选择:需要比较内容时用
==
,需要判断是否为同一对象时用===
。 - 对数组比较,使用
contentEquals
系列函数。
🔗 源码示例可在 GitHub 上找到。