在说原型模式之前先说一下浅拷贝和深拷贝的概念
一、浅拷贝和深拷贝
1、浅拷贝
在java中,对象创建后需要有一个引用变量来指向该对象实际的地址空间,也就是说引用变量与对象实体是两个不同的数据体。在Object类的clone()方法中,对对象字段进行复制时,如果字段是基本数据类型(如int、double等),则会复制字段的值到一个新的变量中,而字段是引用类型(String除外),则仅会将引用值复制给新对象中的相应字段中,也就是说,两个字段指向了同一个对象实例。看以下的例子来理解浅拷贝。
1)用户类
public class User{ private String name; private String sex; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } }
2)学生类:如果要让Student类支持clone方法,必须实现Cloneable接口
public class Student implements Cloneable { private User user; private String message; public User getUser() { return user; } public void setUser(User user) { this.user = user; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } /** * 重写clone()方法为public类型,并调用Object的本地clone()方法,实现浅拷贝功能 */ @Override public Object clone() throws CloneNotSupportedException { return super.clone(); }
3)测试类
public class TestCopy { public static void main(String[] args) throws CloneNotSupportedException { User user = new User(); user.setName("张三"); user.setSex("男"); Student oldStudent = new Student(); oldStudent.setUser(user); oldStudent.setMessage("old message"); System.out.println("oldStudent:"+oldStudent.getUser().getName()+" :"+oldStudent.getUser().getSex()+" :"+oldStudent.getMessage()); Student copyStudent = (Student) oldStudent.clone(); System.out.println("copyStudent:"+copyStudent.getUser().getName()+" :"+copyStudent.getUser().getSex()+" :"+copyStudent.getMessage()); System.out.println("oldStudent == copyStudent ? " +(oldStudent == copyStudent)); copyStudent.getUser().setName("李丽"); copyStudent.getUser().setSex("女"); copyStudent.setMessage("new message"); System.out.println("修改copyStudent的内容后==========="); System.out.println("oldStudent:"+oldStudent.getUser().getName()+" :"+oldStudent.getUser().getSex()+" :"+oldStudent.getMessage()); System.out.println("copyStudent:"+copyStudent.getUser().getName()+" :"+copyStudent.getUser().getSex()+" :"+copyStudent.getMessage()); } }
oldStudent:张三 :男 :old message copyStudent:张三 :男 :old message oldStudent == copyStudent ? false 修改copyStudent的内容后=========== oldStudent:李丽 :女 :old message copyStudent:李丽 :女 :new message
由以上结果可知道,oldStudent和copyStudent并不是同一个对象,当将copyStudent的user信息和message信息修改后,oldStudent的user信息相应也改变了,oldStudent的message没有改变。
得出结论:在进行用Object类对Student的User属性进行拷贝时是浅拷贝,也就是说只是将oldStudent里面user引用变量复制到了copyStudent里面,2个变量实际上指向的是同一块地址。
2、深拷贝
那就是对于引用型变量,深拷贝会开辟一块新的内存空间,将被复制引用所指向的对象实例的各个属性复制到新的内存空间中,然后将新的引用指向块内存(也就是一个新的实例)。以后对新引用指向的实例属性进行修改的时候就不会影响到老引用指向的实例属性。