一、克隆的原理与应用

clone在堆上分配内存,分配的内存和源对象(即调用clone方法的对象)相同,然后再使用原对象中对应的各个域,填充新对象的域, 填充完成之后,clone方法返回,一个新的相同的对象被创建,同样可以把这个新对象的引用发布到外部。如果,想要对该对象进行处理,又想保留原来数据进行接下来的操作,clone就很方便。

二、克隆的实现

1、被克隆的类必须自己实现Cloneable 接口,以指示 Object.clone() 方法可以合法地对该类实例进行按字段复制。Cloneable 接口实际上是个标识接口,没有任何接口方法。

2、覆盖Object.clone()方法。

三、浅拷贝与深拷贝

浅拷贝:在填充新对象域的时候,进行简单的字段赋值。

深拷贝:按照惯例,此方法返回的对象应该独立于该对象(正被复制的对象)。要获得此独立性,在 super.clone 返回对象之前,有必要对该对象的一个或多个字段进行修改。这通常意味着要复制包含正在被复制对象的内部“深层结构”的所有可变对象,并使用对副本的引用替换对这些对象的引用。如果一个类只包含基本字段或对不变对象的引用,那么通常不需要修改 super.clone 返回的对象中的字段。(简单来说,就是将该对象内部的对象也克隆一份,而不是简单的引用赋值)

可变对象:对象创建后字段值可以改变)

浅拷贝:

class Head {
String s;
void set(String s1) {
s = s1;
}
}
public class Person implements Cloneable{ Head head;
Person(Head head) {
this.head = head;
}
protected Object clone() throws CloneNotSupportedException{
return super.clone();
}
public static void main(String[] args) throws CloneNotSupportedException{
Person p = new Person(new Head());
Person p1 = (Person)p.clone();
System.out.println("p == p1 " + (p == p1));
System.out.println("p.head == p1.head " + (p.head == p1.head));
} }

输出结果:

p == p1 false
p.head == p1.head true

结果分析:

可以从结果过中看到,克隆创建了一个新的Person对象,但是p.head与p1.head仍然指向同一对象,也就是说p与p1仍然存在联系,这是我们不想看到的。

深拷贝:

class Head implements Cloneable{
String s;
void set(String s1) {
s = s1;
}
protected Object clone() throws CloneNotSupportedException{
return super.clone();
}
}
public class Person implements Cloneable{ Head head;
Person(Head head) {
this.head = head;
}
protected Object clone() throws CloneNotSupportedException{
Person p = (Person)super.clone();
p.head = (Head)head.clone();
return p;
}
public static void main(String[] args) throws CloneNotSupportedException{
Person p = new Person(new Head());
Person p1 = (Person)p.clone();
System.out.println("p == p1 " + (p == p1));
System.out.println("p.head == p1.head " + (p.head == p1.head));
} }

输出结果:

p == p1 false
p.head == p1.head false

结果分析:要实现深层拷贝要将对象内部的对象拷贝。

好文推荐:详解Java中的clone方法

最新文章

  1. c++ builder 2010 错误 F1004 Internal compiler error at 0x9740d99 with base 0x9
  2. iOS-常见问题
  3. Unity3d 防止内存修改工具的小方法
  4. topcoder SRM 610 DIV2 DivideByZero
  5. MongoDB学习笔记——文档操作之查询
  6. springMVC实现防止重复提交
  7. javaScript内置类Date,Math等
  8. android studio 导入的项目有乱码-笔记2
  9. wxpython StatuBar 带进度条的状态栏
  10. uploadfiy 动态传递Form 参数
  11. GitHub新手使用教学(从安装到使用)
  12. Web浏览器与Web服务器之间的通信过程
  13. 没有显示器、网线、路由器,编辑TF卡连接树莓派
  14. python------面向对象进阶 Socket网络编程
  15. 移动端地区选择控件mobile-select-area
  16. SharePoint中在线编辑文档
  17. C#基础--------------------C#正则表达式
  18. STL 算法介绍
  19. Go基础---->go的基础学习(二)
  20. 背景半透明rgba最佳实践

热门文章

  1. 【luoguP2483】k短路([SDOI2010]魔法猪学院)
  2. jQuery属性操作之DOM属性操作
  3. 2017 ZSTU寒假排位赛 #3
  4. 定义了char**p,为什么能用p[i][j]的形式?p又不是二维数组?
  5. python struct的使用例子
  6. docker mysql容器的安装使用
  7. Android8.0新特性总结
  8. LC 971. Flip Binary Tree To Match Preorder Traversal
  9. [Java复习] 并发 JUC
  10. [jquery]JSON.parse()与JSON.stringify()