Student类:
public class Student implements Cloneable,Serializable{
private static final long serialVersionUID = 4736229991747913221L;
private int age;
private Car car;
//篇幅原因省略构造/get/set方法
@Override
protected Student clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return (Student) super.clone();
}
}
Car类:
public class Car implements Cloneable,Serializable{
private static final long serialVersionUID = 1705363073258599641L;
private int price;
//篇幅原因省略构造/get/set方法
}
一、赋值
public void test1() {
Student zhang=new Student();
zhang.setAge(5);
Student wang=new Student();
System.out.println(zhang+" "+wang);
wang=zhang;
System.out.println(zhang+" "+wang);
System.out.println(wang.getAge());
wang.setAge(6);
System.out.println(zhang.getAge());
}
运行结果:
clone.Student@4459eb14 clone.Student@5a2e4553
clone.Student@4459eb14 clone.Student@4459eb14
5
6
引用类型进行赋值时,赋的值是引用的值,wang=zhang;即将zhang的地址赋值给wang,此时两者指向同一块内存。
二、浅克隆
public void test2() throws CloneNotSupportedException{
Student zhang=new Student(5, new Car(10000));
Student wang=zhang.clone();
System.out.println(zhang+" "+wang);
System.out.println(wang.getAge()+" "+wang.getCar().getPrice());
//改变wang中的普通类型
wang.setAge(6);
//改变wang中的引用类型
wang.getCar().setPrice(200000);
//zhang中的普通类型不变,引用类型被改变
System.out.println(zhang.getAge()+" "+zhang.getCar().getPrice());
}
运行结果:
clone.Student@4459eb14 clone.Student@5a2e4553
5 10000
5 200000
实现Cloneable接口并重写clone方法(见Student类)进行浅拷贝,该方法使wang拥有与zhang不同的引用,但其中的引用类型Car依旧指向同一地址。
三、深克隆
实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆
public void test3() throws Exception{
Student zhang=new Student(5, new Car(10000));
Student wang=MyUtil.clone(zhang);
System.out.println(zhang+" "+wang);
System.out.println(wang.getAge()+" "+wang.getCar().getPrice());
//改变wang中的普通类型
wang.setAge(6);
//改变wang中的引用类型
wang.getCar().setPrice(200000);
//zhang中的普通类型不变,引用类型被改变
System.out.println(zhang.getAge()+" "+zhang.getCar().getPrice());
}
MyUtil类:
public class MyUtil {
private MyUtil() {
throw new AssertionError();
}
@SuppressWarnings("unchecked")
public static <T extends Serializable> T clone(T obj) throws Exception {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bout);
oos.writeObject(obj);
ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bin);
return (T) ois.readObject();
}
}
运行结果:
clone.Student@6d5380c2 clone.Student@3d012ddd
5 10000
5 10000
该方法使wang拥有与zhang不同的引用,其中的引用类型Car也指向不同地址。