Kotlin数据类copy惯用写法如何适配嵌套可空类型场景
Kotlin嵌套可空数据类的copy正确写法
Kotlin数据类的copy()方法仅能修改当前类的直接属性,不支持跨层直接修改深层嵌套属性,嵌套可空场景下需要逐层处理空判断、逐层生成新的拷贝对象。
你给出的判断条件param.subObj?.nextObj?.language == null会命中三类空场景,写copy逻辑时必须全部覆盖,否则会出现默认值赋值失效、空指针问题:
- param的直接属性
subObj为null subObj不为null,但它的内部属性nextObj为nullsubObj、nextObj都不为null,但最终的language属性为null
写法1:逐层判断写法(可读性最高)
语义和你原来的单层copy逻辑完全一致,适合嵌套层级不多的场景:
val options = when { param.subObj == null -> { // subObj为空时,新建完整的嵌套对象链 param.copy( subObj = SubObj( nextObj = NextObj(language = default()) ) ) } param.subObj.nextObj == null -> { // subObj存在但nextObj为空时,保留已有subObj,补全新的nextObj param.copy( subObj = param.subObj.copy( nextObj = NextObj(language = default()) ) ) } param.subObj.nextObj.language == null -> { // 两层嵌套对象都存在,仅language为空时,逐层拷贝修改最深层属性 param.copy( subObj = param.subObj.copy( nextObj = param.subObj.nextObj.copy( language = default() ) ) ) } else -> param }
写法2:作用域函数简化写法
如果觉得逐层判断冗余,可以用安全调用结合 Elvis 操作符压缩代码,逻辑和上面完全一致:
val options = if (param.subObj?.nextObj?.language != null) { param } else { // 先处理最深层的nextObj val fixedNext = param.subObj?.nextObj?.copy(language = default()) ?: NextObj(language = default()) // 再处理中间层subObj val fixedSub = param.subObj?.copy(nextObj = fixedNext) ?: SubObj(nextObj = fixedNext) // 最后修改最外层param param.copy(subObj = fixedSub) }
注意:如果你的业务逻辑不需要在中间层对象为null时自动新建对象,仅当
subObj、nextObj都存在且language为null时才补默认值,只需要保留第三种判断分支即可,此时前置空判断也要对应调整,不能直接使用param.subObj?.nextObj?.language == null。
内容的提问来源于stack exchange,提问作者Felix Dombek
相关产品推荐
相关产品推荐

