用一个已经存在的实例作为原型,创建一个和原型相同的新对象。
结构
- 抽象原型类:规定了具体的原型对象必须实现的clone()方法
- 具体原型类:实现抽象原型类的clone()方法,它是可被复制的对象
- 访问类:使用具体原型类中的clone()方法来复制新的对象
实现
浅克隆:创建一个新对象,新对象的属性和原来的对象完全相同,对于非基本类型属性,仍指向原对象的内存地址
深克隆:对于新创建的对象,属性中引用的对象也会被克隆 不再指向原对象地址
浅克隆
Java中Object类提供了clone()方法实现浅克隆,Cloneable接口是抽象原型类,实现Cloneable接口的子实现类就是具体的原型类
public class ShallowClone implements Cloneable{
public ShallowClone(){
System.out.println("具体原型创建成功");
}
@Override
public ShallowClone clone() throws CloneNotSupportedException {
System.out.println("具体原型复制成功");
return (ShallowClone)super.clone();
}
}
public class Client {
public static void main(String[] args) throws Exception{
ShallowClone s = new ShallowClone();
// 调用原型类中的克隆方法进行克隆
ShallowClone clone = s.clone();
System.out.println(s == clone);
}
}
public class Aware implements Cloneable{
private Student stu;
public Student getStu() {
return stu;
}
public void setStu(Student stu) {
this.stu = stu;
}
@Override
protected Aware clone() throws CloneNotSupportedException {
return (Aware)super.clone();
}
public void show(){
System.out.println(stu.getName() + "获得奖项");
}
}
public class Student {
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class AwareTest {
public static void main(String[] args) throws Exception {
Aware aware = new Aware();
Student student = new Student();
student.setName("李四");
aware.setStu(student);
// 克隆对象
Aware clone = aware.clone();
clone.getStu().setName("张三");
aware.show(); // 张三
clone.show(); //张三
}
}
说明:对于原型aware和克隆对象clone指向的都是同一个地址,当修改clone对象里的stu,原型对象里的值也变为修改后的值。因此,对于原型对象里引用类型的变量应该采用深克隆(对象流)方式进行赋值。(String是特殊的引用数据类型)
深克隆
使用序列化的方式实现对象的深克隆,原型对象及引用型变量都需实现Serializable接口,否则会报NotSerializableException异常
public class AwareTest {
public static void main(String[] args) throws Exception {
Aware aware = new Aware();
Student student = new Student();
student.setName("李四");
aware.setStu(student);
// // 浅克隆对象
// Aware clone = aware.clone();
// clone.getStu().setName("张三");
//
// aware.show(); // 张三
// clone.show(); //张三
// 深克隆:创建对象输出流对象
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\a.txt"));
oos.writeObject(aware);
oos.close();
// 读取对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\a.txt"));
Aware aware1 = (Aware)ois.readObject();
ois.close();
// 修改克隆后的对象
aware1.getStu().setName("张三");
aware.show(); // 李四
aware1.show();//张三
}
}