How to clone object in Kotlin?

2019-03-23 19:27发布

问题:

The question is that simple.

Kotlin documentation describes cloning only in accessing Java and in enum class. In latter case clone is just throwing an exception.

So, how would I / should I clone arbitrary Kotlin object?

Should I just use clone() as in Java?

回答1:

For a data class, you can use the compiler-generated copy() method. Note that it will perform a shallow copy.

To create a copy of a collection, use the toList() or toSet() methods, depending on the collection type you need. These methods always create a new copy of a collection; they also perform a shallow copy.

For other classes, there is no Kotlin-specific cloning solution. You can use .clone() if it suits your requirements, or build a different solution if it doesn't.



回答2:

You can use Gson to convert the original object to a String and then convert back that String to an actual Object type, and you'll have a clone. See my example. Put this function in the class/model of which you want to create a clone. In my example I'm cloning a Project type object so I'll put it in the Project class

class Project{
 fun clone(): Project {
                val stringProject = Gson().toJson(this, Project::class.java)
                return Gson().fromJson<Project>(stringProject, Project::class.java)
            }
}

Then use it like this:

val originalProject = Project()
val projectClone = originalProject.clone()


回答3:

I've voted for @yole for nice answer, but other ways if you don't (or can't) use data class. You can write helper method like this:

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
        }
    }

}

So you can "copy" instance A into B by:

val bInstance = AClassType()
ModelHelper.mergeFields(aInstance, bInstance)

Sometimes, I use this way to merge data from many instances into one object which value available (not null).



标签: kotlin clone