深拷贝与浅拷贝

浅拷贝

public class Student implements Cloneable{
Integer a;
Integer b; @Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
} String c;
Student child;
} public class Main { public static void main(String[] args) throws CloneNotSupportedException {
Student s = new Student();
Student s2 = (Student) s.clone();
System.out.println(s == s2);
System.out.println(s.child == s2.child);
}
}
/**********************************************************************/
false
true

由上述代码及运行结果我们可以看出,调用clone方法之后,确实s2是一个新的对象,内存地址已经发生了改变,但s和s2的child属性仍然指向相同的地址,这便是浅拷贝,当然8种基本数据类型是深拷贝,String则是例外。

深拷贝

public class Teacher implements Cloneable{
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
} public class Student implements Cloneable{
Integer a;
Integer b; public Student(Teacher t) {
this.t = t;
} @Override
protected Object clone() throws CloneNotSupportedException {
Student s = (Student) super.clone();
s.t = (Teacher)s.t.clone();//彻底深拷贝关键
return s;
} String c;
Teacher t;
} public class IntersectionofTwoArraysII { public static void main(String[] args) throws CloneNotSupportedException {
Teacher t = new Teacher();
Student s = new Student(t);
Student s2 = (Student) s.clone();
System.out.println(s == s2);
System.out.println(s.t == s2.t);
}
}
/**********************************************************************/
false
false

如上代码运行结果所示为深拷贝,想要实现深拷贝,就需要在重写Cloneable接口的clone()方法,并调用属性的clone()方法,因此关联类也要实现Cloneable接口,从而形成拷贝链,实现彻底深拷贝

实现彻底的深拷贝并不容易,因为它要求涉及的所有类都实现了cloneable接口,但是如StringBuffer由于其没有实现Cloneable接口,想要实现深拷贝效果,则需要做特殊处理从而实现深拷贝的效果。可以在clone方法中实现

sb=new StringBuffer(sb.toString());

Cloneable接口

Cloneable其实就是一个标记接口,只有实现这个接口后,然后在类中重写Object中的clone方法,然后通过类调用clone方法才能克隆成功,如果不实现Cloneable其实就是一个标记接口接口,调用clone方法则会抛出CloneNotSupportedException(克隆不被支持)异常。

如何判断类是否实现了cloneable接口呢?

/**
* Creates and returns a copy of this {@code Object}. The default
* implementation returns a so-called "shallow" copy: It creates a new
* instance of the same class and then copies the field values (including
* object references) from this instance to the new instance. A "deep" copy,
* in contrast, would also recursively clone nested objects. A subclass that
* needs to implement this kind of cloning should call {@code super.clone()}
* to create the new instance and then create deep copies of the nested,
* mutable objects.
*
* @return a copy of this object.
* @throws CloneNotSupportedException
* if this object's class does not implement the {@code
* Cloneable} interface.
*/
protected Object clone() throws CloneNotSupportedException {
if (!(this instanceof Cloneable)) {
throw new CloneNotSupportedException("Class doesn't implement Cloneable");
} return internalClone((Cloneable) this);
} /*
* Native helper method for cloning.
*/
private native Object internalClone(Cloneable o);

clone方法首先会判对象是否实现了Cloneable接口,若无则抛出CloneNotSupportedException, 最后会调用internalClone. intervalClone是一个native方法,一般来说native方法的执行效率高于非native方法。

参考资料

详解Java中的clone方法 -- 原型模式

最新文章

  1. python之路二
  2. August 28th 2016 Week 36th Sunday
  3. PHP弱类型安全问题的写法和步骤
  4. Python中一些内建函数及os等模块的用法
  5. PHP中mysql_affected_rows()和mysql_num_rows()区别
  6. 1.6.1 什么是 Indexing
  7. mysql颠覆实战笔记(七)--白话理解事务
  8. [POJ 3420] Quad Tiling
  9. Spring MVC Controller配置方式
  10. apache httpd配置ajp报错:ap_proxy_connect_backend disabling worker for (localhost)
  11. COJ 0024 N皇后问题
  12. SqlServer经典函数之数字去零
  13. nova的wsgi介绍【WIP】
  14. [LeetCode]题解(python):003-Longest Substring Without Repeating Characters
  15. ios 修改导航栏返回按钮的图片
  16. SQL Access Advisor in Oracle Database 10g
  17. Delphi 三层框架 DataSnap 的服务器端设置
  18. js知识巩固
  19. AWS Redshift typical error and potential root cause:
  20. 中证500等主要指数的市盈率(PE)估值高度

热门文章

  1. C/C++知识总结 五 复合数据类型 壹(数组、字符串与string、结构)
  2. 1030 Travel Plan (30分)(dijkstra 具有多种决定因素)
  3. on duplicate key update 的用法说明(解决批量操作数据,有就更新,没有就新增)mybatis批量操作数据更新和添加
  4. Redis设计与实现笔记 - hash
  5. .net core 跨平台开发 微服务架构 基于Nginx反向代理 服务集群负载均衡
  6. Scratch 第4课满天星
  7. gdb调试工具常用命令 && kdb
  8. C语言实现链表(链式存储结构)
  9. 本地项目推送到Github
  10. 如何提高你使用windows的逼格(windows用成Linux的赶脚)