java实现深克隆(如HashMap等)
来源:互联网 发布:大数据 微盘 编辑:程序博客网 时间:2024/06/05 13:22
克隆就是复制一个对象的复本.但一个对象中可能有基本数据类型,如:int,long,float 等,也同时含有非基本数据类型如(数组,集合等)
被克隆得到的对象基本类型的值修改了,原对象的值不会改变.这种适合shadow clone(浅克隆).
但如果你要改变一个非基本类型的值时,原对象的值却改变了,.比如一个数组,内存中只copy他的地址,而这个地址指向的值并没有copy,当clone时,两个地址指向了一个值,这样一旦这个值改变了,原来的值当然也变了,因为他们共用一个值.,这就必须得用深克隆(deep clone)
以下举个例子,说明以上情况.
被克隆类:ShadowClone.java
<span style="font-size:14px;">package lc.clone.shadow;public class ShadowClone implements Cloneable{ // 基本类型 private int a; // 非基本类型 private String b; // 非基本类型 private int[] c; // 重写Object.clone()方法,并把protected改为public @Override public Object clone() { ShadowClone sc = null; try { sc = (ShadowClone) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return sc; } public int getA() { return a; } public void setA(int a) { this.a = a; } public String getB() { return b; } public void setB(String b) { this.b = b; } public int[] getC() { return c; } public void setC(int[] c) { this.c = c; }}</span>
测试类Test.java
<span style="font-size:14px;"> package lc.clone.shadow; public class Test { public static void main(String[] args) throws CloneNotSupportedException { ShadowClone c1 = new ShadowClone(); //对c1赋值 c1.setA(100) ; c1.setB("clone1") ; c1.setC(new int[]{1000}) ; System.out.println("克隆前: c1.a="+c1.getA() ); System.out.println("克隆前: c1.b="+c1.getB() ); System.out.println("克隆前: c1.c[0]="+c1.getC()[0]); System.out.println("-----------") ; //克隆出对象c2,并对c2的属性A,B,C进行修改 ShadowClone c2 = (ShadowClone) c1.clone(); //对c2进行修改 c2.setA(50) ; c2.setB("clone2"); int []a = c2.getC() ; a[0]=500 ; c2.setC(a); System.out.println("克隆后: c1.a="+c1.getA() ); System.out.println("克隆后: c1.b="+c1.getB() ); System.out.println("克隆后: c1.c[0]="+c1.getC()[0]); System.out.println("---------------") ; System.out.println("克隆后: c2.a=" + c2.getA()); System.out.println("克隆后: c2.b=" + c2.getB()); System.out.println("克隆后: c2.c[0]=" + c2.getC()[0]); } }</span>
结果:
克隆前: c1.a=100
克隆前: c1.b=clone1
克隆前: c1.c[0]=1000
-----------
克隆后: c1.a=100
克隆后: c1.b=clone1
克隆后: c1.c[0]=500
---------------
克隆后: c2.a=50
克隆后: c2.b=clone2
克隆后: c2.c[0]=500
问题出现了,我指修改了克隆后的对象c2.c的值,但c1.c的值也改变了,与c2的值相等.
以下针对浅克隆得出结论:基本类型是可以被克隆的,但引用类型只是copy地址,并没有copy这个地址指向的对象的值,这使得两个地址指向同一值,修改其中一个,当然另一个也就变了.
由此可见,浅克隆只适合克隆基本类型,对于引用类型就不能实现克隆了.
那如何实现克隆引用对象呢,以下提供一种方法. 用序列化与反序列化实现深克隆(deep copy)
被克隆对象.DeepClone.java
<span style="font-size:14px;">package lc.clone.deep;import java.io.Serializable;//要实现深克隆必须实现Serializable接口public class DeepClone implements Serializable{ private int a; private String b; private int[] c; public int getA() { return a; } public void setA(int a) { this.a = a; } public String getB() { return b; } public void setB(String b) { this.b = b; } public int[] getC() { return c; } public void setC(int[] c) { this.c = c; }}</span>
测试类Test.java
<span style="font-size:14px;">package lc.clone.deep;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;public class Test{ public static void main(String[] args) throws CloneNotSupportedException { Test t = new Test(); DeepClone dc1 = new DeepClone(); // 对dc1赋值 dc1.setA(100); dc1.setB("clone1"); dc1.setC(new int[] { 1000 }); System.out.println("克隆前: dc1.a=" + dc1.getA()); System.out.println("克隆前: dc1.b=" + dc1.getB()); System.out.println("克隆前: dc1.c[0]=" + dc1.getC()[0]); System.out.println("-----------"); DeepClone dc2 = (DeepClone) t.deepClone(dc1); // 对c2进行修改 dc2.setA(50); dc2.setB("clone2"); int[] a = dc2.getC(); a[0] = 500; dc2.setC(a); System.out.println("克隆前: dc1.a=" + dc1.getA()); System.out.println("克隆前: dc1.b=" + dc1.getB()); System.out.println("克隆前: dc1.c[0]=" + dc1.getC()[0]); System.out.println("-----------"); System.out.println("克隆后: dc2.a=" + dc2.getA()); System.out.println("克隆后: dc2.b=" + dc2.getB()); System.out.println("克隆后: dc2.c[0]=" + dc2.getC()[0]); } // 用序列化与反序列化实现深克隆 public Object deepClone(Object src) { Object o = null; try { if (src != null) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(src); oos.close(); ByteArrayInputStream bais = new ByteArrayInputStream(baos .toByteArray()); ObjectInputStream ois = new ObjectInputStream(bais); o = ois.readObject(); ois.close(); } } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return o; }}</span>
结果:
克隆前: dc1.a=100
克隆前: dc1.b=clone1
克隆前: dc1.c[0]=1000
-----------
克隆前: dc1.a=100
克隆前: dc1.b=clone1
克隆前: dc1.c[0]=1000
-----------
克隆后: dc2.a=50
克隆后: dc2.b=clone2
克隆后: dc2.c[0]=500
深克隆后:修改dc1或者dc2,无论是基本类型还是引用类型,他们的值都不会随着一方改变另一方也改变.
总结:当克隆的对象只有基本类型,不含引用类型时,可以用浅克隆实现.
当克隆的对象含有引用类型时,必须使用深克隆实现.
- java实现深克隆(如HashMap等)
- JAVA HASHMAP 如何用
- Java对象克隆方法(浅克隆、深克隆)
- Java对象克隆方法(浅克隆、深克隆)
- java实现shallow clone(浅克隆)与深克隆(deep clone)
- Java深克隆和浅克隆的原理及实现
- JAVA里的深克隆与浅克隆实现
- java对象克隆简单实现(可多级克隆)
- java实现深克隆(deep clone)
- java使用序列化实现深克隆
- java (31) - 序列化实现深克隆
- Java 序列化方式实现深克隆
- Java深克隆浅克隆
- java深克隆浅克隆
- Java浅克隆深克隆
- java 实现对象克隆
- Java(对象的深克隆和浅克隆)
- java心得(深克隆和浅克隆)
- Frozen UI中提取的半像素边框
- gdb 远程调试android进程
- Android—改变LinearLayout背景颜色
- "忘记密码"功能过程及其实现细节
- Cocos2d-x游戏开发——屏幕触摸事件
- java实现深克隆(如HashMap等)
- XNA学习笔记3 鼠标响应
- AJAX中文乱码总结
- C++ 异常
- jxcx_Hermes(Mdrill)安装-1
- 信用卡还款
- 三层问题—“系统找不到指定的文件”
- 函数1、Linux下的打印函数printk
- .NET开发者必备的工具箱