class MainKotlin {
@Test
fun test0() {
val oriList = ArrayList<Model>()
val model0 = Model(0, "name0")
val model1 = Model(1, "name1")
val model2 = Model(2, "name2")
oriList.add(model0)
oriList.add(model1)
oriList.add(model2)
val copyList = ArrayList<Model>()
oriList.forEach {
copyList.add(it.clone())
println("list = $oriList")
println("copyList = $copyList")
println("======== change name ========")
model0.name = "name0 changed"
println("list = $oriList")
println("copyList = $copyList")
class Model(): Cloneable {
var id: Int? = null
var name: String? = null
constructor(id: Int, name: String) : this() {
this.id = id
this.name = name
// 添加 try catch, 防止奇怪的异常
public override fun clone(): Model {
return try {
return super.clone() as? Model ?: Model()
} catch (e: CloneNotSupportedException) {
Model()
override fun toString(): String {
return "Model(id=$id, name=$name)"
输出结果:
可以看到 model0 更改 name 时, list 随之改变, copyList 没有改变, 成功~
今天在做单例的时候, 被数据的一些状态整懵了, 虽然想到了可以通过深拷贝解决问题, 但竟然直接使用了 newList.addAll(oldList) ... 结果又排查问题查了半天...才想到 list 中的 model 也是要完全 new 出来才行, model 里面那么多属性, 一个一个赋值太不优雅啦, 在网上查了下可以通过:
- clone 实现
- 实现序列化, 通过反序列化 new 出来对象
- 转成 json 字符串, 再转成对象(解析最好在子线程)
序列化深拷贝实现见 后续补充.
java的一个类,如果要使用 Cloneable 实现拷贝功能, 需要先实现这个接口, 然后重写Object的clone方法. 对于类中的引用类型的属性, 需要在clone方法中实现深拷贝, 否则就是浅拷贝.
属性中有引用对象的话, 引用对象也要实现 Cloneable, 然后这个引用对象也要调用 clone 方法才行...有点麻烦, 得封装一下才好用...后续带封装...
后续待优化:
可以把 集合 的深拷贝封装一个函数, 这样调用起来比较方便, 待执行任务...
序列化实现, 有两种, Serializable 和 Parcelable
Serializable 存在文件读写的过程, Parcelable 是在内存中操作, 建议使用 Parcelabel.
1. Serializable 实现
当前需要类实现 Serializable 接口, 并且如果成员变量有引用类型, 此引用类型也需要实现 Serializable 接口, 这样深拷贝才能成功
java 代码
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class DeepCopyUtil {
public static Object deepClone(Serializable obj) {
Object anotherObj = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = null;
ObjectInputStream ois = null;
try {
oos = new ObjectOutputStream(baos);
oos.writeObject(obj);
byte[] bytes = baos.toByteArray();
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
ois = new ObjectInputStream(bais);
anotherObj = ois.readObject();
} catch (Exception ex) {
} finally {
if (oos != null) {
try {
oos.close();
} catch (IOException localIOException3) {
Logger.e("deepClone error:"+localIOException3.getMessage());
if (ois != null) {
try {
ois.close();
} catch (IOException localIOException4) {
return anotherObj;
kotlin 代码
fun <T : Serializable> T.deepCopy(obj: T?): T? {
if (obj == null) return null
val baos = ByteArrayOutputStream()
val oos = ObjectOutputStream(baos)
oos.writeObject(obj)
oos.close()
val bais = ByteArrayInputStream(baos.toByteArray())
val ois = ObjectInputStream(bais)
@Suppress("unchecked_cast")
return ois.readObject() as T
2. Parcelable 实现
注意 parcelabel 需要在 android 环境中测试, 在 java 中会报异常 java.lang.RuntimeException: Stub!...
参考 https://farhanpatel.dev/index.php/2020/06/14/deep-clones-with-android-parcelable/
fun <T : Parcelable> deepClone(objectToClone: T): T? {
var parcel: Parcel? = null
return try {
parcel = Parcel.obtain()
parcel.writeParcelable(objectToClone, 0)
parcel.setDataPosition(0)
parcel.readParcelable(objectToClone::class.java.classLoader)
} finally {
//it is important to recyle parcel and free up resources once done.
parcel?.recycle()
Java的浅拷贝(Shallow Copy)、深拷贝(Deep Copy)。
浅拷贝(Shallow Copy):
1、对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将该属性值复制一份给新的对象。因为是两份不同的数据,所以对其中一个对象的该成员变量值进行修改,不会影响另一个对象拷贝得到的数据。
2、对于数据类型是引用数据类型的成员变量,比如说成员变量是某个数组、某个类的对象等,那么浅拷贝会进行引用传递,也就是只是将该成员变量的引用值(内存地址)复制一份给新的对象。因为实际上两个对象的.
import
java.util.*
import
kotlin.collections.Array
List
import
kotlin.reflect.full.createInstance
import
kotlin.reflect.full.memberProperties
import
kotlin.reflect.jvm.
javaField
* @Description: 用来复制元素的工具类
* @Author: dk
* @Date: 2021/6/28 12:05 PM
为了使查询出来的数据不受到污染,经常会将数据拷贝到一个可以随意使用的集合中,而在期间的就需要进行copy操作。
以前的我使用循环遍历(for循环)然后存到另一个集合中,但是这样会有很多冗余代码,且for循环影响程序执行效率(数据很多的情况下)
为了简化代码,我找到了Collection中的copy方法,该方法会将原集合数据(src)copy到目的集合(dest)
Collections.co...
kotlin Cloneable 的奇怪行为
在使用 kotlin 的 Cloneable 时,发现它表示得很奇怪。如果类直接继承了 Cloneable ,那么它的表现很正常
和 java 的使用差不多,如下:
package demo
interface Foo {
fun createClone(): Foo
fun doSomething()
class Bar: F...
深拷贝和浅拷贝是只针对Object和Array这样的引用数据类型
浅拷贝(Shadow
Clone)
浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。
深拷贝(Deep
Clone)
深拷贝会另外创建一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
深拷贝实现方式(4种)
序列化然后反序列化对象后,得到一个新对象
手动创建新对象,遇到对象和数组时,手动创建新对象并将其赋值,手动创建新数组并遍历赋值
重写
kotlin data class c
fun main(args: Array<String>) {
val list = mutableListOf("one", "two")
val c1 = Container(list)
val c2 = c1.copy()
list += "o.
在Android Studio中将Kotlin转换为Java,可以使用以下步骤:
1. 打开Kotlin文件,右键单击文件名并选择“Convert Kotlin File to Java File”选项。
2. 在弹出的对话框中,选择要转换的文件和目标文件夹。
3. 点击“OK”按钮开始转换过程。
4. 转换完成后,将在目标文件夹中生成Java文件。
需要注意的是,转换过程中可能会出现一些语法错误或类型转换问题,需要手动进行修复。此外,转换后的Java代码可能不如原始的Kotlin代码简洁和易读。