在Object中有clone()方法
protected Object clone() throws CloneNotSupportedException
clone()的作用是创建一个该对象的一个副本,并将对象的数据复制到该副本中
根据复制程度的不同,clone可以分为:
浅拷贝:使用clone()即为浅拷贝,默认的拷贝方式是复制一个新的原对象,并赋予原对象相同的全局对象的值和引用。即原对象和复制对象的全局引用变量指向的是一个相同的对象空间。
深拷贝:需要自己实现,即将原对象中的全局引用变量指向的对象也复制一份放入复制对象中。
这两个概念可能不太好理解,可以根据下面的案例来加深理解。
首先明确对Object clone的要求
- 实现Cloneable接口,如果不实现该接口会在clone方法中抛出CloneNotSupportedException异常
- 需要重写clone方法,clone方法在Object中是protect的,不能被外部访问,需要重写并修改为public的访问权限。
运行类
class Test{
@Test
public void ttt() throws CloneNotSupportedException {
A a=new A();
B b=new B();
a.setName("one");
a.setB(b);
b.setAge(1);
A ca= (A) a.clone();
a.setName("two");
a.getB().setAge(2);
System.out.print("a.name="+a.getName()+"\n"+
"a.b.age="+a.getB().getAge()+"\n"+
"ca.name="+ca.getName()+"\n"+
"ca.b.age="+ca.getB().getAge());
//打印
/*
a.name=two
a.b.age=2
ca.name=one
ca.b.age=2
*/
}
}
class A implements Cloneable{
private String name;
private B b;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public B getB() {
return b;
}
public void setB(B b) {
this.b = b;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class B implements Cloneable{
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
上面的案例即为浅拷贝,可以看到ca为a的拷贝对象,但是两个对象的b指向的是同一个B的对象。
进行深拷贝:
需要修改A中的clone方法
@Override
public Object clone() throws CloneNotSupportedException {
A o=null;
o=(A)super.clone();
if(o.b!=null){
o.b=(B)o.b.clone();
}
return o;
}
在test中的打印结果为:
a.name=two
a.b.age=2
ca.name=one
ca.b.age=1
另一种利用序列化来实现对象的深拷贝
需要序列化,首先要让A和B都实现Serializable接口
在A中添加深拷贝方法
public Object deepClone() throws IOException, 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();
}
该方法先将可序列化对象a写入流中,再将对象从流中读出来重建对象
参考博客:
java.lang.Object.clone()分析
Java Object对象之clone方法
Object的clone()方法、深拷贝、浅拷贝