- 浏览: 529734 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (119)
- java总结 (43)
- Spring (2)
- 反编译工具 (1)
- hibernate (1)
- Tomcat (1)
- WebLogic (2)
- 随笔 (4)
- Word问题小记 (2)
- web前端 (26)
- Oracle (10)
- DOS (1)
- 面试笔试 (3)
- Servlet (1)
- jQuery (1)
- Linux/Unix (2)
- JSTL (1)
- struts2 (2)
- JSON (2)
- Velocity (0)
- 生活 (3)
- MyEclipse使用小结 (1)
- 操作系统 (2)
- jqgrid (1)
- ajax-dwr (1)
- javascript (18)
- dreamweaver (2)
- html (10)
- css (5)
- 正则表达式 (1)
- IO (3)
最新评论
-
a363722188:
幽默者 写道老兄,Collections.copy(dest1 ...
由java中深度复制一伸出Collections.copy的使用 -
幽默者:
老兄,Collections.copy(dest1, src1 ...
由java中深度复制一伸出Collections.copy的使用 -
raymao:
java 中 split 是正则表达式
java 和 javascript split 的区别! -
413899327:
面试前端javascript
阿里电话面试 -
yzsunlight:
你面试前台UI?
阿里电话面试
⑴浅复制(浅克隆)
被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。
⑵深复制(深克隆)
被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。
Java的clone()方法
⑴clone方法将对象复制了一份并返回给调用者。一般而言,clone()方法满足:
①对任何的对象x,都有x.clone() !=x//克隆对象与原对象不是同一个对象
②对任何的对象x,都有x.clone().getClass()= =x.getClass()//克隆对象与原对象的类型一样
③如果对象x的equals()方法定义恰当,那么x.clone().equals(x)应该成立。
⑵Java中对象的克隆
①为了获取对象的一份拷贝,我们可以利用Object类的clone()方法。
②在派生类中覆盖基类的clone()方法,并声明为public。
③在派生类的clone()方法中,调用super.clone()。
④在派生类中实现Cloneable接口。
s2变了,但s1也变了,证明s1的p和s2的p指向的是同一个对象。这在我们有的实际需求中,却不是这样,因而我们需要深拷贝:
①为什么我们在派生类中覆盖Object的clone()方法时,一定要调用super.clone()呢?在运行时刻,Object中的 clone()识别出你要复制的是哪一个对象,然后为此对象分配空间,并进行对象的复制,将原始对象的内容一一复制到新对象的存储空间中。
②继承自java.lang.Object类的clone()方法是浅复制。以下代码可以证明之。
当然我们还有一种深拷贝方法,就是将对象串行化:
但是串行化却很耗时,在一些框架中,我们便可以感受到,它们往往将对象进行串行化后进行传递,耗时较多。
3.利用串行化来做深复制
把对象写到流里的过程是串行化(Serilization)过程,但是在Java程序师圈子里又非常形象地称为“冷冻”或者“腌咸菜(picking)”过程;而把对象从流中读出来的并行化(Deserialization)过程则叫做“解冻”或者“回鲜(depicking)”过程。应当指出的是,写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面,因此“腌成咸菜”的只是对象的一个拷贝,Java咸菜还可以回鲜。
在Java语言里深复制一个对象,常常可以先使对象实现Serializable接口,然后把对象(实际上只是对象的一个拷贝)写到一个流里(腌成咸菜),再从流里读出来(把咸菜回鲜),便可以重建对象。
如下为深复制源代码。
public Object deepClone()
{
//将对象写到流里
ByteArrayOutoutStream bo=new ByteArrayOutputStream();
ObjectOutputStream oo=new ObjectOutputStream(bo);
oo.writeObject(this);
//从流里读出来
ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray());
ObjectInputStream oi=new ObjectInputStream(bi);
return(oi.readObject());
}
这样做的前提是对象以及对象内部所有引用到的对象都是可串行化的,否则,就需要仔细考察那些不可串行化的对象可否设成transient,从而将之排除在复制过程之外。
被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。
⑵深复制(深克隆)
被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。
Java的clone()方法
⑴clone方法将对象复制了一份并返回给调用者。一般而言,clone()方法满足:
①对任何的对象x,都有x.clone() !=x//克隆对象与原对象不是同一个对象
②对任何的对象x,都有x.clone().getClass()= =x.getClass()//克隆对象与原对象的类型一样
③如果对象x的equals()方法定义恰当,那么x.clone().equals(x)应该成立。
⑵Java中对象的克隆
①为了获取对象的一份拷贝,我们可以利用Object类的clone()方法。
②在派生类中覆盖基类的clone()方法,并声明为public。
③在派生类的clone()方法中,调用super.clone()。
④在派生类中实现Cloneable接口。
class Professor0 implements Cloneable { String name; int age; Professor0(String name, int age) { this.name = name; this.age = age; } public Object clone() throws CloneNotSupportedException { return super.clone(); } } class Student0 implements Cloneable { String name;// 常量对象。 int age; Professor0 p;// 学生1和学生2的引用值都是一样的。 Student0(String name, int age, Professor0 p) { this.name = name; this.age = age; this.p = p; } public Object clone() { Student0 o = null; try { o = (Student0) super.clone(); } catch (CloneNotSupportedException e) { System.out.println(e.toString()); } return o; } } public class ShallowCopy { public static void main(String[] args) { Professor0 p = new Professor0("wangwu", 50); Student0 s1 = new Student0("zhangsan", 18, p); Student0 s2 = (Student0) s1.clone(); s2.p.name = "lisi"; s2.p.age = 30; s2.name = "z"; s2.age = 45; System.out.println("学生s1的姓名:" + s1.name + "\n学生s1教授的姓名:" + s1.p.name + "," + "\n学生s1教授的年纪" + s1.p.age);// 学生1的教授 } }
s2变了,但s1也变了,证明s1的p和s2的p指向的是同一个对象。这在我们有的实际需求中,却不是这样,因而我们需要深拷贝:
class Professor implements Cloneable { String name; int age; Professor(String name, int age) { this.name = name; this.age = age; } public Object clone() { Object o = null; try { o = super.clone(); } catch (CloneNotSupportedException e) { System.out.println(e.toString()); } return o; } } class Student implements Cloneable { String name; int age; Professor p; Student(String name, int age, Professor p) { this.name = name; this.age = age; this.p = p; } public Object clone() { Student o = null; try { o = (Student) super.clone(); } catch (CloneNotSupportedException e) { System.out.println(e.toString()); } o.p = (Professor) p.clone(); return o; } } public class DeepCopy { public static void main(String args[]) { long t1 = System.currentTimeMillis(); Professor p = new Professor("wangwu", 50); Student s1 = new Student("zhangsan", 18, p); Student s2 = (Student) s1.clone(); s2.p.name = "lisi"; s2.p.age = 30; System.out.println("name=" + s1.p.name + "," + "age=" + s1.p.age);// 学生1的教授不改变。 long t2 = System.currentTimeMillis(); System.out.println(t2-t1); } }
①为什么我们在派生类中覆盖Object的clone()方法时,一定要调用super.clone()呢?在运行时刻,Object中的 clone()识别出你要复制的是哪一个对象,然后为此对象分配空间,并进行对象的复制,将原始对象的内容一一复制到新对象的存储空间中。
②继承自java.lang.Object类的clone()方法是浅复制。以下代码可以证明之。
当然我们还有一种深拷贝方法,就是将对象串行化:
import java.io.*; //Serialization is time-consuming class Professor2 implements Serializable { /** * */ private static final long serialVersionUID = 1L; String name; int age; Professor2(String name, int age) { this.name = name; this.age = age; } } class Student2 implements Serializable { /** * */ private static final long serialVersionUID = 1L; String name;// 常量对象。 int age; Professor2 p;// 学生1和学生2的引用值都是一样的。 Student2(String name, int age, Professor2 p) { this.name = name; this.age = age; this.p = p; } public Object deepClone() throws IOException, OptionalDataException, ClassNotFoundException { // 将对象写到流里 ByteArrayOutputStream bo = new ByteArrayOutputStream(); ObjectOutputStream oo = new ObjectOutputStream(bo); oo.writeObject(this); // 从流里读出来 ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray()); ObjectInputStream oi = new ObjectInputStream(bi); return (oi.readObject()); } } public class DeepCopy2 { /** * @param args */ public static void main(String[] args) throws OptionalDataException, IOException, ClassNotFoundException { long t1 = System.currentTimeMillis(); Professor2 p = new Professor2("wangwu", 50); Student2 s1 = new Student2("zhangsan", 18, p); Student2 s2 = (Student2) s1.deepClone(); s2.p.name = "lisi"; s2.p.age = 30; System.out.println("name=" + s1.p.name + "," + "age=" + s1.p.age); // 学生1的教授不改变。 long t2 = System.currentTimeMillis(); System.out.println(t2-t1); } }
但是串行化却很耗时,在一些框架中,我们便可以感受到,它们往往将对象进行串行化后进行传递,耗时较多。
3.利用串行化来做深复制
把对象写到流里的过程是串行化(Serilization)过程,但是在Java程序师圈子里又非常形象地称为“冷冻”或者“腌咸菜(picking)”过程;而把对象从流中读出来的并行化(Deserialization)过程则叫做“解冻”或者“回鲜(depicking)”过程。应当指出的是,写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面,因此“腌成咸菜”的只是对象的一个拷贝,Java咸菜还可以回鲜。
在Java语言里深复制一个对象,常常可以先使对象实现Serializable接口,然后把对象(实际上只是对象的一个拷贝)写到一个流里(腌成咸菜),再从流里读出来(把咸菜回鲜),便可以重建对象。
如下为深复制源代码。
public Object deepClone()
{
//将对象写到流里
ByteArrayOutoutStream bo=new ByteArrayOutputStream();
ObjectOutputStream oo=new ObjectOutputStream(bo);
oo.writeObject(this);
//从流里读出来
ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray());
ObjectInputStream oi=new ObjectInputStream(bi);
return(oi.readObject());
}
这样做的前提是对象以及对象内部所有引用到的对象都是可串行化的,否则,就需要仔细考察那些不可串行化的对象可否设成transient,从而将之排除在复制过程之外。
发表评论
-
文件操作待整理
2013-10-16 16:14 1665package test; import java. ... -
Java追加文件内容的三种方法
2013-10-16 15:22 8935/** * 描述:追加内容到文件末尾 ... -
jajva IO常用写法
2013-10-16 13:58 1152// 指定编码读取文件路径创建缓冲输入流 Buffered ... -
Java 使用正则表达式从文件中解析出所有email地址
2013-10-16 13:36 14327import java.io.File; import ... -
java 和 javascript split 的区别!
2013-09-18 10:52 1570java 和 javascript split 的区别! ... -
javascrip如何创建命名空间
2013-09-18 10:49 1149看代码,废话不多说! <!DOCTYPE ht ... -
请教个问题,java在后台跑的线程如何控制他的超时时间,超过一段时间自动停止?
2013-03-22 09:43 1079请教个问题,java在后台跑的线程如何控制他的超时时间,超过一 ... -
java 用jdbc方式以 sys账号连接oracle数据的问题
2013-02-26 11:53 9595jdbc.properties driver=oracl ... -
由java中深度复制一伸出Collections.copy的使用
2012-12-16 23:59 38601今天在学习集合中 有关对象的深度拷贝和浅拷贝 的时候,像拷贝一 ... -
java中ArrayList深拷贝有关问题
2012-12-16 23:50 6073基本思路就是将要深拷贝的对象实现Serializable接口。 ... -
JAVA 时间 和 js里面时间的区别
2012-04-13 11:31 2360JAVA 里面处理时间时,只要按照format格式去解析时间, ... -
java 多级目录创建文件
2011-12-21 10:43 5627方式一: File file = new File(&q ... -
java获取文件名的三种方法
2011-10-09 15:47 77440import java.io.File; imp ... -
三种for循环样式
2011-09-27 20:42 1393三种for循环样式 1、for(int i = 0;i & ... -
随机生成颜色
2011-08-25 09:24 5528import java.util.Random; ... -
在Eclipse下运行是不能使用Console类
2011-07-07 23:43 3094在Eclipse下运行是不能使用Console类。 Con ... -
3种Java从文件路径中获取文件名的方法
2011-05-11 09:53 30446package test; import java.i ... -
数组转集合Collections:Arrays.asList(values)
2011-05-05 17:23 1821将一个数组转换为list集合时,使用List <数组类型 ... -
迭代Map
2011-04-13 09:13 1083for ( Iterator iterator = aM ... -
详解Java重载(Overload)
2010-12-11 22:20 1809重载(Overload) 覆 ...
相关推荐
NULL 博文链接:https://bijian1013.iteye.com/blog/2358367
List对象排序通用方法List对象排序通用方法List对象排序通用方法List对象排序通用方法
Java关于深拷贝(深复制)和浅拷贝(浅复制)比较通俗易懂的简单说明及示例代码...
java对象的深拷贝和浅拷贝[归类].pdf
Java CopyUtil工具类,可以进行对象的深copy,比如:对象里面包含对象,对象里面包含Map,List,Set...等复杂类型的属性都可以copy,copy后的对象与原有对象没有联系,即改变原有对象内容,不会改变copy后的对象里面的...
首先我们看看浅拷贝和深拷贝的定义 浅拷贝:只复制一个对象,对象内部存在的指向其他对象... 深拷贝:对象,对象内部的引用均复制 为了更好的理解它们的区别我们假设有一个对象A,它包含有2对象对象A1和对象A2
NULL 博文链接:https://1064319393.iteye.com/blog/2114611
今天小编就为大家分享一篇关于Java Clone深拷贝与浅拷贝的两种实现方法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
拷贝对象是java中经常会遇到的问题。java中存在两种类型,基础类型和引用类型。...Object对象中提供了一个clone方法,来供我们对java对象进行拷贝。 protected native Object clone() throws CloneNot
Java 对象拷贝是为对象赋值的一种方式,简单来说就是创建一个和原对象相同的对象,新创建的对象是原对象的一个副本,面试官贼拉喜欢在面试的时候问一问你浅拷贝和深拷贝的原理。因为它涉及到对象的引用关系,涉及到 ...
java通用转echart方法(亲测试多种格式,暂时能满足使用)
java 操作文件通用方法集合,很实用的方法
深度复制Java对象实例,复制后对象属性值改变不影响被复制对象,有注释
主要介绍了java中List对象排序通用方法,涉及java针对List对象的操作技巧,需要的朋友可以参考下
节制2013年12月23日最新的hadoop和hbase兼容版本搭建 hadoop-2.2.0 hbase-0.96.1.1 java Hbase java DBHelper CRUD等通用方法 花了两天时间整理的,含有lib包 & 源码
详细描述了java基础中的数组与方法的应用技术,以及面向对象的过程思想,有助于java初学者的入门学习。
里面是xml转换成为java对象的两种方法,
通用的Java常见方法,学习参考!!!!!!
model VO 值复制 注解 注解实现相同对象,不同对象,集合与集合复制,不再需要手动。 可以对多个对象进行复制,可以指定复制的类型
主要介绍了Java中实现深拷贝的两种方式—clone() & Serialized,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧