Kotlin使用==比较data class时类内属性是否参与相等判断
结论
你的理解完全正确,这段断言会错误通过,两个实例的name字段差异根本没被==校验到,是Kotlin语言特性和Gson库机制叠加导致的结果。
原因说明
1. Kotlin data class 的相等判断逻辑
Kotlin 里data class自动生成的equals()(也就是==操作符实际调用的方法)、hashCode()、copy()这些方法,只会将主构造函数中声明的属性纳入计算范围,定义在类体内部的属性不会参与这些自动生成的逻辑。
你定义的X类主构造里只有isThatSo: Boolean一个属性,类体里写的name属于类内部成员,自动生成的相等判断完全不会校验它的值,只要两个实例的isThatSo一致,==就会返回true。
data class X(val isThatSo: Boolean) { val name:String = "xyz" }
哪怕两个实例的name值一个是"Ankit"一个是"xyz",只要isThatSo都是true,比较结果就是相等。
2. Gson 反序列化Kotlin类的固有问题
Gson 是原生为Java设计的序列化库,本身不识别Kotlin的主构造函数、属性默认值、空安全等语法特性:
- 反序列化时Gson不会调用类的主构造方法,而是通过底层
Unsafe接口直接分配内存创建空实例,再通过反射把JSON里的字段值挨个注入对象 - 你提供的JSON中包含
"name": "Ankit"字段,Gson会直接通过反射把这个值写入实例的name属性,完全无视这个属性不在主构造、有预设默认值的设定 - 如果JSON中缺失某个字段,Gson会直接给对应字段赋Java类型的默认零值:对象类型赋值
null、布尔类型赋值false、数值类型赋值0,你在代码里写的默认值逻辑根本不会触发。
你测试代码里JSON把isThatSo的值写成字符串"true"也能正常反序列化,也是Gson默认做了宽松类型转换的结果,不影响核心判断逻辑。
修复方式
- 把需要参与相等判断、需要默认值生效的属性全部挪到data class的主构造函数中:
data class X( val isThatSo: Boolean, val name: String = "xyz" )
修改后自动生成的equals方法会把name纳入校验,两个实例name不一致时==就会正确返回false。
- 尽量不要用原生Gson反序列化Kotlin data class,优先选择对Kotlin有原生支持的序列化实现,比如kotlinx.serialization、带Kotlin代码生成适配的Moshi;如果必须使用Gson,需要额外接入对应的Kotlin适配适配器,避免绕过构造函数的问题。
内容的提问来源于stack exchange,提问作者Ankit
相关产品推荐
相关产品推荐

