java深克隆和浅克隆
来源:互联网 发布:linux可视化调试工具 编辑:程序博客网 时间:2024/05/02 01:54
java深克隆和浅克隆
克隆就是复制一个对象的复本.但一个对象中可能有基本数据类型,如:int,long,float 等,也同时含有非基本数据类型如(数组,集合等)
被克隆得到的对象基本类型的值修改了,原对象的值不会改变.这种适合shadow clone(浅克隆).
但如果你要改变一个非基本类型的值时,原对象的值却改变了,.比如一个数组,内存中只copy他的地址,而这个地址指向的值并没有copy,当clone时,两个地址指向了一个值,这样一旦这个值改变了,原来的值当然也变了,因为他们共用一个值.,这就必须得用深克隆(deep clone)
以下举个例子,说明以上情况:
被克隆类:ShadowClone.java
class ShallowCloneimplements Cloneable {
public int a;
public int[] b;
public ShallowClone() {
a = 5;
b = new int[] {1,2,3,4,5};
}
// 浅克隆,对于克隆后的对象,只能保证对基础类型成员的修改不会影响原对象的相应成员
// 对类类型和数组类型的成员,只是拷贝了对象的地址,因此对克隆后对象的这些类型成员
// 进行修改会影响原对象
@Override
public Object clone() {
ShallowClone sc =null;
try {
sc = (ShallowClone)super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return sc;
}
}
public int a;
public int[] b;
public ShallowClone() {
a = 5;
b = new int[] {1,2,3,4,5};
}
// 浅克隆,对于克隆后的对象,只能保证对基础类型成员的修改不会影响原对象的相应成员
// 对类类型和数组类型的成员,只是拷贝了对象的地址,因此对克隆后对象的这些类型成员
// 进行修改会影响原对象
@Override
public Object clone() {
ShallowClone sc =null;
try {
sc = (ShallowClone)super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return sc;
}
}
测试类:
publicclass DeepAndShallowClone {
public static void main(String[] args)throws Exception {
// shallow clone
ShallowClone sc=new ShallowClone();
ShallowClone scCopy = (ShallowClone)sc.clone();
System.out.println("Shallow Copy");
System.out.println("--Before clone");
System.out.println("sc.a="+ sc.a);
System.out.println("sc.b="+ sc.b[0]);
scCopy.a = 1;
scCopy.b[0]=10;
System.out.println("--After clone");
System.out.println("sc.a="+ sc.a);
System.out.println("sc.b="+ sc.b[0]);
System.out.println("scCopy.a="+ scCopy.a);
System.out.println("scCopy.b="+ scCopy.b[0]);
}
}
public static void main(String[] args)throws Exception {
// shallow clone
ShallowClone sc=new ShallowClone();
ShallowClone scCopy = (ShallowClone)sc.clone();
System.out.println("Shallow Copy");
System.out.println("--Before clone");
System.out.println("sc.a="+ sc.a);
System.out.println("sc.b="+ sc.b[0]);
scCopy.a = 1;
scCopy.b[0]=10;
System.out.println("--After clone");
System.out.println("sc.a="+ sc.a);
System.out.println("sc.b="+ sc.b[0]);
System.out.println("scCopy.a="+ scCopy.a);
System.out.println("scCopy.b="+ scCopy.b[0]);
}
}
结果如下:
Shallow Copy
--Before clone
sc.a=5
sc.b=1
--After clone
sc.a=5
sc.b=10
scCopy.a=1
scCopy.b=10
--Before clone
sc.a=5
sc.b=1
--After clone
sc.a=5
sc.b=10
scCopy.a=1
scCopy.b=10
问题出现了,修改了克隆后的对象scCopy.b[0]的值,但sc.b[0]的值也改变了,与scCopy.b[0]的值相等.
以下针对浅克隆得出结论:基本类型是可以被克隆的,但引用类型只是copy地址,并没有copy这个地址指向的对象的值,这使得两个地址指向同一值,修改其中一个,当然另一个也就变了.
由此可见,浅克隆只适合克隆基本类型,对于引用类型就不能实现克隆了.
那如何实现克隆引用对象呢,需要克隆的引用对象不多时可以逐个复制引用对象。当数量较多时,以下提供一种方法,非常好用:用序列化与反序列化实现深克隆(deep copy)
被克隆对象.DeepClone.java
class DeepCloneimplements Serializable {
private static finallong serialVersionUID=1L;
public int a;
public int[] b;
public DeepClone() {
a = 10;
b = new int[] {6,7,8,9,10};
}
// 使用ObjectInput(Output)Stream和ByteArrayInput(Output)Stream实现深克隆
public Object deepClone()throws IOException, ClassNotFoundException {
DeepClone dc =null;
ByteArrayOutputStream baos =new ByteArrayOutputStream();
ObjectOutputStream oos =new ObjectOutputStream(baos);
oos.writeObject(this);
oos.close();
ByteArrayInputStream bais =new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream bis =new ObjectInputStream(bais);
dc = (DeepClone)bis.readObject();
return dc;
}
}
private static finallong serialVersionUID=1L;
public int a;
public int[] b;
public DeepClone() {
a = 10;
b = new int[] {6,7,8,9,10};
}
// 使用ObjectInput(Output)Stream和ByteArrayInput(Output)Stream实现深克隆
public Object deepClone()throws IOException, ClassNotFoundException {
DeepClone dc =null;
ByteArrayOutputStream baos =new ByteArrayOutputStream();
ObjectOutputStream oos =new ObjectOutputStream(baos);
oos.writeObject(this);
oos.close();
ByteArrayInputStream bais =new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream bis =new ObjectInputStream(bais);
dc = (DeepClone)bis.readObject();
return dc;
}
}
测试类:
publicclass DeepAndShallowClone {
public static void main(String[] args)throws Exception {
DeepClone dc =new DeepClone();
DeepClone dcCopy = (DeepClone)dc.deepClone();
System.out.println("--Before clone");
System.out.println("dc.a="+ dc.a);
System.out.println("dc.b="+ dc.b[0]);
dcCopy.a = 1;
dcCopy.b[0]=1;
System.out.println("Shallow Copy");
System.out.println("--After clone");
System.out.println("dc.a="+ dc.a);
System.out.println("dc.b="+ dc.b[0]);
System.out.println("dcCopy.a="+ dcCopy.a);
System.out.println("dcCopy.b="+ dcCopy.b[0]);
}
}
public static void main(String[] args)throws Exception {
DeepClone dc =new DeepClone();
DeepClone dcCopy = (DeepClone)dc.deepClone();
System.out.println("--Before clone");
System.out.println("dc.a="+ dc.a);
System.out.println("dc.b="+ dc.b[0]);
dcCopy.a = 1;
dcCopy.b[0]=1;
System.out.println("Shallow Copy");
System.out.println("--After clone");
System.out.println("dc.a="+ dc.a);
System.out.println("dc.b="+ dc.b[0]);
System.out.println("dcCopy.a="+ dcCopy.a);
System.out.println("dcCopy.b="+ dcCopy.b[0]);
}
}
结果如下:
--Before clone
dc.a=10
dc.b=6
Shallow Copy
--After clone
dc.a=10
dc.b=6
dcCopy.a=1
dcCopy.b=1
dc.a=10
dc.b=6
Shallow Copy
--After clone
dc.a=10
dc.b=6
dcCopy.a=1
dcCopy.b=1
writeObject方法会将被克隆类的对象关系网都写出,这样就可以实现深克隆。当然,每个被克隆的成员类型必须实现Serializable接口
- java深克隆和浅克隆
- java深克隆和浅克隆
- java 深克隆和浅克隆区别
- java中的深克隆和浅克隆
- Java的深克隆和浅克隆
- JAVA中的深克隆和浅克隆
- java 深克隆和浅克隆
- Java中的浅克隆和深克隆
- java浅克隆和深克隆
- 理解Java浅克隆和深克隆
- java的克隆(深克隆和浅克隆)
- java对象克隆(浅克隆和深克隆)
- java克隆之深克隆和浅克隆
- Java深克隆浅克隆
- java深克隆浅克隆
- Java浅克隆深克隆
- 浅克隆和深克隆
- 深克隆和浅克隆
- sstream使用范例
- 清洁和时尚的CSS3的表格
- axis2与web项目结合
- 朋友,请不要焦虑
- Ubuntu 15.04 上安装VMware-Workstation 11
- java深克隆和浅克隆
- Linux编程库简介
- == 如何做好计算机科学研究 ==
- sql中的事物
- 位域操作符
- 使用非2次方幂的图像纹理的问题
- osgEarth linux 编译
- IOS的app程序中的文件目录的功能和使用详细说明
- josephus问题用面向对象的方法来实现