java進行對象複製當然客以new 一個新的對象然後把原來對象的屬性值挨個複製到新的對象中去,可萬一屬性三四十個呢,不是很麻煩,於是便有了Java的Clone方法
Java對象要想具有Clone方法,首先要實現Cloneable接口,重寫Clone()方法,如
public class A implements Cloneable{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return super.clone();
}
}
Test方法
public void Test1() throws CloneNotSupportedException{
A a=new A();
a.setAge(22);
a.setName("張三");
A a1=(A) a.clone();
System.out.println(a1==a);
System.out.println(a1.getName()+":"+a1.getAge());
}
結果:
false
張三:22
可見Clone生成兩個不同的對象,而不僅僅是複製了地址的引用
但是有個問題是,Clone() 只支持全局變量類型爲8種基本類型和String類型的複製,對比如Date,ArrayList等其他引用類型只是複製了地址引用,這樣Clone出來的對象就失去了原有的意義了,即成爲淺度複製
如:
package cn.zw.learn.prototype;
public class A implements Cloneable{
private String name;
private int age;
private B b;
public B getB() {
return b;
}
public void setB(B b) {
this.b = b;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return super.clone();
}
}
測試
public void Test1() throws CloneNotSupportedException{
A a=new A();
a.setAge(22);
a.setName("張三");
B b=new B();
b.setName("褲子");
a.setB(b);
A a1=(A) a.clone();
System.out.println(a1==a);
System.out.println(a.getB()==a1.getB());
System.out.println(a1.getName()+":"+a1.getAge());
}
}
結果
false
true
張三:22
這樣兩個對象就不完全獨立,失去了克隆的意義
爲了解決這一問題,我們在實現的clone()方法中,用序列化反序列化的方式得到一個新的Object並把它作爲返回值返回,做深度複製
改造如下
B類加上實現序列化接口
A類改造如下
package cn.zw.learn.prototype;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
public class A implements Cloneable,Serializable{
private String name;
private int age;
private B b;
public B getB() {
return b;
}
public void setB(B b) {
this.b = b;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public Object clone() throws CloneNotSupportedException {
ByteArrayOutputStream bos=null;
ObjectOutputStream oos=null;
ObjectInputStream ois=null;
try {
bos=new ByteArrayOutputStream();
oos=new ObjectOutputStream(bos);
oos.writeObject(this);
ois=new ObjectInputStream( new ByteArrayInputStream(bos.toByteArray()));
A a1= (A) ois.readObject();
return a1;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
//下面的部分爲關閉流主要是上面的部分
if (oos!=null) {
try {
oos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (ois!=null) {
try {
ois.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (oos!=null) {
try {
oos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return null;
}
}
測試類大致不變
public void Test1() throws CloneNotSupportedException{
A a=new A();
a.setAge(22);
a.setName("張三");
B b=new B();
b.setName("褲子");
a.setB(b);
A a1=(A) a.clone();
System.out.println(a1==a);
System.out.println(a.getB()==a1.getB());
System.out.println(a1.getName()+":"+a1.getAge()+"," +a1.getB().getName());
}
}
結果如下
false
false
張三:22,褲子
完全沒有關係的兩個對象,且屬性全部複製,深度Clone