Kotlin带字段校验的数据类:如何让toString输出对外属性而非私有构造参数
问题根源说明
Kotlin 数据类自动生成的 toString()、equals()、hashCode() 方法,仅会识别主构造函数中通过 val/var 修饰的属性——无论这些属性是公开还是私有,都会被纳入默认生成的逻辑中。
原实现里把_x、_y作为主构造的private val参数,自然会被默认toString捕获,才会输出内部私有参数的名字。
最符合Kotlin习惯的简洁实现
完全不需要依赖反射逻辑,仅需两步调整:
- 把主构造里的私有
val参数改成无修饰的临时入参:这类参数只是构造时的临时传值载体,不会成为类的成员,也不会被数据类的自动逻辑捕获 - 手写一行极简的toString方法,直接输出对外暴露的公共属性
完整可运行代码如下:
data class MutablePointKt( initialX: Int = 0, initialY: Int = 0 ) { // 用Kotlin原生require做参数校验,替代第三方Validate依赖 private fun validatePositiveOrZero(value: Int) { require(value >= 0) { "negative coordinate provided: $value" } } var x: Int = 0 get() { println(" > getting x: $field") return field } set(value) { validatePositiveOrZero(value) field = value } var y: Int = 0 get() { println(" > getting y: $field") return field } set(value) { validatePositiveOrZero(value) field = value } init { // 用带校验逻辑的setter完成初始值赋值 x = initialX y = initialY } // 一行替代全部反射逻辑 override fun toString(): String = "MutablePointKt(x=$x, y=$y)" } // 运行输出完全符合预期 println(MutablePointKt(1, 2)) // 输出:MutablePointKt(x=1, y=2)
对比原反射方案的优势
- 无额外第三方依赖,完全基于Kotlin原生能力实现
- 代码量减少70%以上,无冗余的自定义ToStringStyle类
- 运行时无反射遍历的性能开销,字符串拼接逻辑执行效率更高
- 逻辑完全显式,后续新增属性时可以直接在toString里补充,不需要维护字段过滤规则
注意:如果类属性数量超过10个,手写toString的成本会升高,这时候再考虑反射实现的方案;对于两个属性的简单数据类,手写是最直接、最符合Kotlin简洁性原则的选择。
内容的提问来源于stack exchange,提问作者spi
相关产品推荐
相关产品推荐

