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