17.克隆
克隆
一、基本数据类型的克隆
基本数据类型的克隆 直接赋值就可以实现克隆的效果
例如:
Int a=50;
Int b=a;
二、对象类型的克隆
为什么要克隆?
大家先思考一个问题,为什么需要克隆对象?直接new一个对象不行吗?
答案是:克隆的对象可能包含一些已经修改过的属性,而new出来的对象的属性都还是初始化时候的值,所以当需要一个新的对象来保存当前对象的“状态”就靠clone方法了。那么我把这个对象的临时属性一个一个的赋值给我新new的对象不也行嘛?可以是可以,但是一来麻烦不说,二来,大家通过上面的源码都发现了clone是一个native方法,就是快啊,在底层实现的。
提个醒,我们常见的Object a=new Object();Object b;b=a;这种形式的代码复制的是引用,即对象在内存中的地址,a和b对象仍然指向了同一个对象。
而通过clone方法赋值的对象跟原来的对象时同时独立存在的。
三、对象的克隆方式 浅克隆/深克隆
1.浅克隆
克隆的对象内不包含成员对象,只有基本数据推荐使用浅克隆
如果对象内包含成员对象,则不能实现对成员对象的克隆,只是完成对成员对象地址的引用
浅克隆的实现:
-
实现Cloneable接口
-
重写clone方法
public Object clone() { return super.clone(); }
2. 深克隆
可以克隆对象的所有内容包括成员对象。
实现对象克隆有两种方式:
1). 实现Cloneable接口并重写Object类中的clone()方法;
2). 实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真 正的深度克隆
实现方式一、
-
成员对象需要实现Cloneable接口 并重写clone()方法。
-
原对象的clone()方法中 需要 调用 成员对象的clone()方法,并把返回值赋值给成员对象
-
缺点:如果当前克隆对象的成员对象很多就很麻烦
public Object clone() {
Object object =null;
try {
object = super.clone();
if (addr != null) {
setAddr((Addr) addr.clone());
}
} catch (CloneNotSupportedException e) {
e.printStackTrace();
object = null;
}
return object;
}
实现方式二:
-
如果引用类型里面还包含很多引用类型,或者内层引用类型的类里面又包含引用类型,使用clone方法就会很麻烦。这时我们可以用序列化的方式来实现对象的深克隆。
-
原对象和成员对象都要实现Sirializable接口,然后只需要在原对象中自定义一个方法来实现对象的序列化用于对象的克隆
-
步骤解析
创建一个字节输出流把当前对象放入输出流中
再创建一个字节输入流把对象读取回来
public Demo myClone() throws IOException, ClassNotFoundException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream outputStream = new ObjectOutputStream(out);
outputStream.writeObject(this)
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
ObjectInputStream inputStream = new ObjectInputStream(in);
Demo demo = (Demo) inputStream.readObject();
return demo;
}
相关克隆的问题:
-
使用克隆是否一定要实现Cloneable和Serializable
-
String类克隆的时候怎么操作
解答:
-
深克隆中有两种方法
(1) 第一种:实现Cloneable接口,并且重写clone()方法,而且类型中属性包含成员对象的,成员对象也要实现Cloneable接口,并且重写clone()方法,原对象还需调用成员对象的clone()方法;
(2) 使用序列化和反序列化实现克隆,前提时类必须实现Serializable接口
(3) 第一和第二种方法一起使用两个克隆方法
-
String类型为引用类型 默认final修饰,克隆时使用浅克隆就可以
String value=“原值”;
Demo.setValue(value); 当对象设置了value值时,复制了一份value的内存引用地址给demo.value(如果之后修改了value的值,也不会影响demo.value的值)
value =“新值”;
value重新指向了新的内存地址(新内存地址指向的是新值),原值依旧存在(也就是demo.value引用地址所指的值)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义