为何Kotlin代码最后一行输出false?data class与class差异解析
问题原因解释
核心前提
HashSet 判断元素是否存在的逻辑是:先通过元素的 hashCode() 找到对应的哈希桶,再在桶内用 equals() 方法匹配元素。而 Kotlin 的 data class 和普通 class 在 equals()、hashCode() 的实现上有本质差异,这是导致结果不同的关键。
一、Data Class 输出 false 的原因
- Data Class 的默认行为:Kotlin 的
data class会自动基于所有声明的属性(这里是name和surName)生成equals()和hashCode()方法。也就是说,两个Person对象是否相等、hashCode()的计算值,完全由这两个属性的取值决定。 - 执行过程拆解:
- 初始化
person(name="AA")并加入HashSet时,HashSet会根据此时的hashCode()(基于AA+BB计算)把对象放到对应的哈希桶里。 - 修改
person.name = "TEST"后,该对象的hashCode()会基于新的属性值重新计算,发生了变化,但HashSet不会自动更新对象在内部哈希桶中的位置。 - 调用
person in names时,HashSet会用当前的hashCode()找新的哈希桶,这个桶里没有目标对象;而原来存放该对象的旧哈希桶,HashSet不会去遍历查找,最终返回false。
- 初始化
二、普通 Class 输出 true 的原因
- 普通 Class 的默认行为:普通
class没有重写equals()和hashCode(),直接继承自Object类的实现:equals()判断的是对象引用是否相同(等价于 Kotlin 中的===),和属性值无关。hashCode()返回的是基于对象内存地址的固定值,不会因为属性修改而变化。
- 执行过程拆解:
- 即使修改了
person.name,person的对象引用没有变,hashCode()值也保持不变。 - 调用
person in names时,HashSet通过原来的hashCode()找到对应的哈希桶,然后用equals()比较引用,发现集合里的元素就是当前的person对象,所以返回true。
- 即使修改了
内容的提问来源于stack exchange,提问作者Hack123
相关产品推荐
相关产品推荐

