Kotlin为何没有默认.clone()方法?是否有简便替代方案?
Kotlin 为何无默认拷贝方法及普通类拷贝解决方案
为什么Kotlin没有默认的clone()方法
Kotlin 刻意避开了 Java 的clone()机制,核心原因是这套设计本身存在诸多缺陷:
Cloneable接口仅作为标记,未定义clone()方法,违反接口的设计原则;clone()方法的浅拷贝行为不明确,对于引用类型的属性,是否复制完全依赖子类实现;- 必须处理
CloneNotSupportedException,增加了代码冗余; - 拷贝逻辑与类的构造逻辑分离,容易出现属性新增后拷贝逻辑未同步的问题。
Kotlin 选择用更明确的方式提供拷贝能力,比如数据类的copy()方法、集合的toList()/toSet()等,都是基于明确的构造逻辑实现,避免了 Java clone()的模糊性。
普通类的简便拷贝方案
1. 浅拷贝的实现
方式一:IDE自动生成拷贝方法
对于简单类,直接用IDE(IntelliJ/Android Studio)的自动生成功能:右键类内部 → Generate → Copy Function,IDE会自动根据主构造函数生成copy()方法,无需手动编写代码。
比如你的SomeClass:
class SomeClass(val intParam: Int, val strParam: String) { fun copy(intParam: Int = this.intParam, strParam: String = this.strParam): SomeClass { return SomeClass(intParam, strParam) } }
方式二:通用反射实现浅拷贝
如果有多个普通类需要拷贝,可以写一个通用的扩展函数,利用Kotlin反射自动复制所有主构造函数参数:
import kotlin.reflect.full.memberProperties import kotlin.reflect.full.primaryConstructor fun <T : Any> T.shallowCopy(): T { val primaryConstructor = this::class.primaryConstructor ?: throw IllegalArgumentException("目标类必须包含主构造函数") val propertyValues = this::class.memberProperties.associate { property -> property.name to property.get(this) } return primaryConstructor.callBy(propertyValues) }
使用时直接调用:
val original = SomeClass(1, "test") val copy = original.shallowCopy()
注意:需要在项目中添加Kotlin反射依赖(Gradle项目可添加implementation("org.jetbrains.kotlin:kotlin-reflect:${kotlin_version}"))。
2. 深拷贝的实现
方式一:序列化实现深拷贝
利用kotlinx.serialization库,通过序列化+反序列化实现通用深拷贝,无需手动处理每个属性:
- 添加Gradle依赖:
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0")
- 给类添加
@Serializable注解并实现通用扩展函数:
import kotlinx.serialization.Serializable import kotlinx.serialization.decodeFromString import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json @Serializable class SomeClass(val intParam: Int, val strParam: String) fun <T : @Serializable Any> T.deepCopy(): T { return Json.decodeFromString(Json.encodeToString(this)) }
使用示例:
val original = SomeClass(2, "deep test") val deepCopy = original.deepCopy()
方式二:第三方工具类
如果项目中已经依赖Apache Commons Lang,可以用SerializationUtils.clone(),前提是类实现Serializable接口:
import org.apache.commons.lang3.SerializationUtils import java.io.Serializable class SomeClass(val intParam: Int, val strParam: String) : Serializable // 使用 val copy = SerializationUtils.clone(original)
总结
如果只是简单浅拷贝,IDE自动生成或通用反射函数足够解决问题;需要深拷贝时,序列化是最简便的通用方案,无需为每个类编写繁琐的拷贝逻辑。
内容的提问来源于stack exchange,提问作者Vladimir Petrunko
相关产品推荐
相关产品推荐

