android全局复制代码,Android Kotlin 全局深拷贝的扩展函数

本文介绍如何利用Kotlin的扩展函数特性,创建一个全局的深拷贝函数,适用于Android开发中需要复制对象的情况。通过反射创建新实例,并遍历原对象的所有属性进行赋值,支持多种数据类型,包括基本类型、字符串、数组、集合、Map等。文中还提供了单元测试用例来验证深拷贝的正确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

基于Kotlin的扩展函数的特性,我们能很容易封装一个全局的函数来实现某些功能

如全局的UI线程回调函数,不管在代码的任何地方,都可以让指定代码块运行到UI线程上

这次就分享一个深拷贝的扩展函数

思路就是通过反射创建一个新的实例,然后读出要拷贝的对象每一个属性的值再重新怼回去

具体可以看代码是怎么实现的

/深拷贝

fun T.deepCopy(): T {

val copiedObjects = mutableMapOf()

var initialObject = getValueFromCopiedCollection(this,copiedObjects)

initialObject = deepCopy(this, copiedObjects)

return initialObject

}

private fun deepCopy(obj: T,copiedObjects: MutableMap): T{

val objClassJava = obj::class.java

val objClass = obj::class

// 基本数据类型直接返回

if (objClassJava.isPrimitive) {

return obj

} else {

if (objClass.javaPrimitiveType != null) {

return obj

}

}

when(obj){

is String -> {

val newString = String(obj.toCharArray())

copiedObjects[obj] = newString

return newString as T

}

is Array -> {

val arrList = ArrayList()

val newArray: Any

for (elem in obj){

if (elem == null)

arrList.add(elem)

else

arrList.add(getValueFromCopiedCollection(elem, copiedObjects))

}

newArray = obj.clone()

arrList.toArray(newArray)

copiedObjects[obj] = newArray

return newArray as T

}

is List -> {

val arrList = ArrayList()

for (elem in obj){

if (elem == null)

arrList.add(elem)

else

arrList.add(getValueFromCopiedCollection(elem, copiedObjects))

copiedObjects[obj] = arrList

}

}

is Map -> {

val newMap = mutableMapOf()

for ((key,value) in obj){

if (key == null){

if (value == null)

newMap[key] = value

else

newMap[key] = getValueFromCopiedCollection(value,copiedObjects)

} else {

if (value === null)

newMap[getValueFromCopiedCollection(key,copiedObjects)] = value

else

newMap[getValueFromCopiedCollection(key,copiedObjects)] = getValueFromCopiedCollection(value,copiedObjects)

}

}

copiedObjects[obj] = newMap

return newMap as T

}

is Set -> {

val newSet = mutableSetOf()

for (elem in obj){

if (elem == null)

newSet.add(elem)

else

newSet.add(getValueFromCopiedCollection(elem, copiedObjects))

}

copiedObjects[obj] = newSet

return newSet as T

}

is Date -> {

return Date(obj.time) as T

}

else -> {

println("deepCopy, class name: ${objClass.simpleName}")

val properties = objClass.memberProperties

val newCopy = objClassJava.newInstance()

properties.forEach {prop ->

val field = prop.javaField

if (field != null){

field.isAccessible = true

val value = field.get(obj)

val type = field.type

if (value == null)

field.set(newCopy, value)

else

field.set(newCopy, getValueFromCopiedCollection(value,copiedObjects))

}

}

copiedObjects[obj] = newCopy

return newCopy

}

}

//傻逼kotlin,前面都return完了,还要强行你这样写,虽然可以return when,但是代码不直观

return obj

}

private fun getValueFromCopiedCollection(value: T,

copiedObjects: MutableMap): T{

if (copiedObjects.containsKey(value)){

return copiedObjects[value] as T

}

var tempValue: Any? = null

if (!value::class.java.isPrimitive

&& value::class.javaPrimitiveType == null

&& !value::class.java.isArray

&& (value !is Collection)){

tempValue = value::class.createInstance()

}

if (copiedObjects.isNotEmpty()){

tempValue = deepCopy(value,copiedObjects)

}

if (tempValue == null)

tempValue = value

else

copiedObjects[value] = tempValue

return tempValue as T

}

单元测试(用法)

class DeepCloneTest {

@Test

fun testThisClone() {

val thisCopy = deepCopy()

assertFalse(thisCopy === this)

}

@Test

fun testStringClone() {

val string = "水天滑稽天照八野滑稽石"

val stringClone = string.deepCopy()

assertNotNull(stringClone)

assertEquals(string, stringClone)

assertFalse(string === stringClone)

}

@Test

fun testIntegerPrimitiveClone() {

val integer = 100500

val integerClone = integer.deepCopy()

assertNotNull(integerClone)

assertTrue(integer == integerClone)

}

@Test

fun testIntegerClone() {

val integer = Integer(100500)

val integerClone = integer.deepCopy()

println(integerClone.toString())

assertNotNull(integerClone)

assertTrue(integer == integerClone)

}

@Test

fun testListClone() {

val listOfStrings = listOf("a", "b", "c")

val listOfStringsClone = listOfStrings.deepCopy() as List

assertNotNull(listOfStringsClone)

assertTrue(listOfStringsClone.isNotEmpty())

assertTrue(listOfStringsClone.size == 3)

}

@Test

fun testSimpleObjectClone() {

val simpleObject = SimpleObject()

val simpleObjectClone = simpleObject.deepCopy()

assertNotNull(simpleObjectClone)

assertTrue(simpleObject == simpleObjectClone)

assertFalse(simpleObject === simpleObjectClone)

}

@Test

fun testComplexObjectClone() {

val complexObject = ComplexObject()

val complexObjectClone = complexObject.deepCopy()

assertNotNull(complexObjectClone)

assertFalse(complexObject === complexObjectClone)

}

}

data class SimpleObject(

var foo: String = "foo",

var bar: String = "bar"

)

class ComplexObject {

val noField: String

get() {

return "123"

}

var a = 1

get() = field + 1

set(value) {

field = value + 5

}

val b = 2

var listExample = mutableListOf(1, 2, 3)

var mapExample = mutableMapOf(1 to 1, 2 to 2, 3 to 3)

var arrExample = arrayOf(arrayOf(1, 2, 3), 2, 3)

var hashMapExample = hashMapOf(1 to 2, 3 to 2, 2 to 3)

var setExample = setOf(1, 2, 3)

var nullableInt: Int? = null

var date = Date()

val simpleNestedObject = SimpleObject()

}

全部通过就没事了,具体实现和用法简单看下代码也就明白啦~

1e53c8347ccc

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值