You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin数据类copy惯用写法如何适配嵌套可空类型场景

Kotlin嵌套可空数据类的copy正确写法

Kotlin数据类的copy()方法仅能修改当前类的直接属性,不支持跨层直接修改深层嵌套属性,嵌套可空场景下需要逐层处理空判断、逐层生成新的拷贝对象。

你给出的判断条件param.subObj?.nextObj?.language == null会命中三类空场景,写copy逻辑时必须全部覆盖,否则会出现默认值赋值失效、空指针问题:

  • param的直接属性subObj为null
  • subObj不为null,但它的内部属性nextObj为null
  • subObj、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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 15:54:15