克隆
对象的克隆可以分为深克隆和浅克隆
浅克隆
Object类中定义了clone()方法可以实现对象的克隆
(浅克隆),通过克隆的方式创建对象的成本远远小于new操作--原型模式
如果需要某种类型的对象支持克隆操作,则要求类型实现一个接口Cloneable是一个标志接口, 用于告知浏览器这个类型的对象需要支持克隆操作
Cloneable接口没有定义成员。它通常用于指明被创建的一个允许对对象进行位复制(也就是对象副本)的类。如果试图用一个不支持Cloneable接口的类调用clone( )方法,将引发一个CloneNotSupportedException异常。当一个副本被创建时,并没有调用被复制对象的构造函数 。副本仅仅是原对象的一个简单精确的拷贝。
import java.util.Date;
public class Test1 {
public static void main(String[] args) throws Exception {
A1 aa=new A1();
aa.setId(99);
aa.setName("zhangsan");
aa.setBirth(new Date());
aa.setWork(new StringBuffer("包工头"));
A1 bb= (A1) aa.clone();
System.out.println(bb);
System.out.println(aa==bb);
System.out.println(aa.equals(bb));
aa.getBirth().setYear(9000); //修改的是aa对象中的引用类型属性birth,查看的是aa对象
System.out.println(bb);
aa.setName(aa.getName()+"bb");
System.out.println(bb);
aa.setWork(aa.getWork().append("内蒙人"));
System.out.println(bb);
bb.setWork(new StringBuffer("左门"));
System.out.println(aa);
}
}
//注意:A1类必须实现Cloneable接口,否则运行就会异常
class A1 implements Cloneable{
private int id;
private String name;//不可变类型
private Date birth;
private StringBuffer work;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
//============================================
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public StringBuffer getWork() {
return work;
}
public void setWork(StringBuffer work) {
this.work = work;
}
@Override
public String toString() {
return "A1 [id=" + id + ", name=" + name + ", birth=" + birth + ", work=" + work + "]";
}
}
深克隆
如果需要实现深克隆,可以通过对象流实现,会将所有相关的内容进行一次拷贝,而不会针对复杂类型属性只是拷贝地址(浅克隆)
如果需要实现深克隆,可以通过对象流【Serializable】实现,会将所有相关的内容进行一次拷贝,而不会针对复杂类型属性只是拷贝地址(浅克隆)
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Date;
public class Test2 {
public static void main(String[] args) throws Exception {
A2 aa=new A2();
aa.setId(99);
aa.setName("zhangsan");
aa.setBirth(new Date());
aa.setWork(new StringBuffer("包工头"));
ByteArrayOutputStream baos=new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(baos);
oos.writeObject(aa);
oos.close();
ObjectInputStream ois=new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
Object obj=ois.readObject();
ois.close();
A2 bb = (A2)obj;
System.out.println(bb);
System.out.println(aa == bb);
System.out.println(aa.equals(bb));
aa.getBirth().setYear(9000);
System.out.println(bb); // 修改的是aa对象中的引用类型属性birth,查看的是aa对象
aa.setName(aa.getName() + "bb");
System.out.println(bb);
aa.setWork(aa.getWork().append("美梦人"));
System.out.println(bb);
bb.setWork(new StringBuffer("左门"));
System.out.println(aa);
}
}
class A2 implements Serializable{ //Externalizable
private int id;
private String name;//不可变类型
private Date birth;
private StringBuffer work;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
//============================================
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public StringBuffer getWork() {
return work;
}
public void setWork(StringBuffer work) {
this.work = work;
}
@Override
public String toString() {
return "A1 [id=" + id + ", name=" + name + ", birth=" + birth + ", work=" + work + "]";
}
}