自己写的深度克隆的小例子,需要实现Cloneable接口. 克隆时加了个null判断,在其他例子中不经常看到,也不知道是否应该进行判断.随便看看吧 import java.util.Vector;/** * 深度克隆. 要求实现克隆接口 */public class A implements Cloneable { // 数组克隆 public String name[]; // 对象克隆 public Vector<B> claB; /** * 构造方法 */ public A() { name = new String[2]; claB = new Vector<B>(); } /** * 重写克隆方法. 深度克隆 */ @Override public Object clone() { A o = null; try { o = (A) super.clone();
// vector对象的克隆 o.claB = new Vector<B>();// 将clone进行到底 if(claB != null){ // 在一些例子中没有这句null判断,为避免错误,这句是我自己加上的,不知道是否应该. for (int i = 0; i < claB.size(); i++) { B temp = (B) claB.get(i).clone();// 当然ClassB也要实现相应clone方法 o.claB.add(temp); } }else{ o.claB = null; } } catch (CloneNotSupportedException e) { e.printStackTrace(); } return o; } /** * 克隆类中包含其他类时,深度克隆时,其他类也要实现克隆接口. */ private class B implements Cloneable { private String b1; private String b2; public String getB1() { return b1; } public void setB1(String b1) { this.b1 = b1; } public String getB2() { return b2; } public void setB2(String b2) { this.b2 = b2; }
/** * 重写克隆方法 */ @Override public Object clone() { A o = null; try { o = (A) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return o; } } }
简单的说,对于基本类型来说,只有深拷贝,对于引用类型来说,有浅拷贝和深拷贝两种浅拷贝,就是用一个变量的值(即变量的内存信息)直接对另一个变量赋值 如 A a = new A(); A b = a; //浅拷贝,就是把a的值赋给b,也就是说把a的内存信息复制到b的内存 为什么说是浅拷贝,因为这样的话,a和b指向相同的对象,所以改变a的属性会引起b属性的改变,不能达到a和b是互相独立互不影响的效果,所以称这样的拷贝为"浅"拷贝,也就是一种虚假的拷贝,并没能达到b完完全全是a的复制品深拷贝,就是让变量指向一个新的对象,并用另一个对象的信息初始化新的对象 如 A a = new A(); ... A b = new A(); b.xxx = a.xxx; //用a.xxx初始化b.xxx属性,如果a.xxx属性不是基本类型,那么也要像b那样重新生成一个xxx对象,让b.xxx指向该对象,并且用a.xxx的信息去初始化新的对象 这样的话,改变a的属性不会影响b属性的改变,也就是说a和b是互不影响的,所以称这样的拷贝为"深"拷贝,b是a的一个完完全全的复制品
class A { private int age; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public A dClone() { A ret = new A(); ret.setAge(this.getAge()); return ret; } }public class Test8 { private int bb; private A arg; public int getBb() { return this.bb; } public void setBb(int bb) { this.bb = bb; } public A getArg() { return this.arg; } public void setArg(A arg) { this.arg = arg; } public Test8() { arg = new A(); arg.setAge(12); } public Test8 dClone() { Test8 ret = new Test8(); ret.setBb(this.getBb()); ret.setArg(this.getArg().dClone()); return ret ; } public static void main(String[] args) { Test8 b = new Test8(); System.out.println(b + "-----" + b.getArg()); Test8 b1 = b.dClone(); System.out.println(b1 + "-----" + b1.getArg()); // 两次打印的应该是不一样的 }}结果:Test8@c3c749-----A@150bd4d Test8@12b6651-----A@4a5ab2
如果成员变量是对象的话,必须要获得该对象的cloneimport java.util.*;public class MyObject
{
private int num;
private Date date;
public Object clone()
{
MyObject object = new MyObject();
object.num = num; //基本类型直接赋值
object.date = (Date) date.clone(); //对象必须要clone
return object;
}
}
克隆时加了个null判断,在其他例子中不经常看到,也不知道是否应该进行判断.随便看看吧
import java.util.Vector;/**
* 深度克隆. 要求实现克隆接口
*/public class A implements Cloneable {
// 数组克隆
public String name[];
// 对象克隆
public Vector<B> claB; /**
* 构造方法
*/
public A() {
name = new String[2];
claB = new Vector<B>();
} /**
* 重写克隆方法. 深度克隆
*/
@Override
public Object clone() {
A o = null;
try {
o = (A) super.clone();
// name对象的克隆
if(name != null){ // 在一些例子中没有这句null判断,为避免错误,这句是我自己加上的,不知道是否应该.
o.name = (String[]) name.clone();// 深度clone
}else{
o.name = null;
}
// vector对象的克隆
o.claB = new Vector<B>();// 将clone进行到底
if(claB != null){ // 在一些例子中没有这句null判断,为避免错误,这句是我自己加上的,不知道是否应该.
for (int i = 0; i < claB.size(); i++) {
B temp = (B) claB.get(i).clone();// 当然ClassB也要实现相应clone方法
o.claB.add(temp);
}
}else{
o.claB = null;
}
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return o;
} /**
* 克隆类中包含其他类时,深度克隆时,其他类也要实现克隆接口.
*/
private class B implements Cloneable {
private String b1; private String b2; public String getB1() {
return b1;
} public void setB1(String b1) {
this.b1 = b1;
} public String getB2() {
return b2;
} public void setB2(String b2) {
this.b2 = b2;
}
/**
* 重写克隆方法
*/
@Override
public Object clone() {
A o = null;
try {
o = (A) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return o;
}
}
}
如
A a = new A();
A b = a; //浅拷贝,就是把a的值赋给b,也就是说把a的内存信息复制到b的内存
为什么说是浅拷贝,因为这样的话,a和b指向相同的对象,所以改变a的属性会引起b属性的改变,不能达到a和b是互相独立互不影响的效果,所以称这样的拷贝为"浅"拷贝,也就是一种虚假的拷贝,并没能达到b完完全全是a的复制品深拷贝,就是让变量指向一个新的对象,并用另一个对象的信息初始化新的对象
如
A a = new A();
...
A b = new A();
b.xxx = a.xxx; //用a.xxx初始化b.xxx属性,如果a.xxx属性不是基本类型,那么也要像b那样重新生成一个xxx对象,让b.xxx指向该对象,并且用a.xxx的信息去初始化新的对象
这样的话,改变a的属性不会影响b属性的改变,也就是说a和b是互不影响的,所以称这样的拷贝为"深"拷贝,b是a的一个完完全全的复制品
private int age; public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} public A dClone() {
A ret = new A();
ret.setAge(this.getAge());
return ret;
}
}public class Test8 { private int bb;
private A arg; public int getBb() {
return this.bb;
} public void setBb(int bb) {
this.bb = bb;
} public A getArg() {
return this.arg;
} public void setArg(A arg) {
this.arg = arg;
} public Test8() {
arg = new A();
arg.setAge(12);
} public Test8 dClone() {
Test8 ret = new Test8();
ret.setBb(this.getBb());
ret.setArg(this.getArg().dClone());
return ret ;
} public static void main(String[] args) {
Test8 b = new Test8();
System.out.println(b + "-----" + b.getArg()); Test8 b1 = b.dClone();
System.out.println(b1 + "-----" + b1.getArg()); // 两次打印的应该是不一样的 }}结果:Test8@c3c749-----A@150bd4d
Test8@12b6651-----A@4a5ab2