问题很简单。
Kotlin文件describes cloning only in accessing Java and in enum class。在后一种情况下,克隆只是抛出异常。
那么,我将如何克隆任意Kotlin对象?
我应该像Java一样使用clone()
吗?
对于data class
,您可以使用编译器生成的copy()
method。请注意,它将执行浅拷贝。
要创建集合的副本,请使用toList()
或toSet()
方法,具体取决于您需要的集合类型。这些方法总是创建集合的新副本;他们也执行浅拷贝。
对于其他类,没有Kotlin特定的克隆解决方案。如果符合您的要求,您可以使用.clone()
,如果不符合,可以使用不同的解决方案。
您可以使用Gson将原始对象转换为String,然后将该String转换回实际的Object类型,并且您将拥有一个克隆。看看我的例子。将此函数放在要创建克隆的类/模型中。在我的例子中,我正在克隆一个Project类型对象,所以我将它放在Project类中
class Project{
fun clone(): Project {
val stringProject = Gson().toJson(this, Project::class.java)
return Gson().fromJson<Project>(stringProject, Project::class.java)
}
}
然后像这样使用它:
val originalProject = Project()
val projectClone = originalProject.clone()
它需要为您的类实现Cloneable,然后像公共一样覆盖clone():
public override fun clone(): Any {<your_clone_code>}
https://discuss.kotlinlang.org/t/how-to-use-cloneable/2364/3
我已经投票给@yole以获得不错的答案,但是如果您不(或不能)使用数据类,则会采用其他方式。你可以写这样的辅助方法:
object ModelHelper {
inline fun <reified T : Serializable> mergeFields(from: T, to: T) {
from::class.java.declaredFields.forEach { field ->
val isLocked = field.isAccessible
field.isAccessible = true
if (field.get(from) != null) {
field.set(to, field.get(from))
}
field.isAccessible = isLocked
}
}
}
因此,您可以通过以下方式将实例A“复制”到B中:
val bInstance = AClassType()
ModelHelper.mergeFields(aInstance, bInstance)
有时,我使用这种方式将来自许多实例的数据合并到一个值可用的对象(非空)。