赞
踩
什么是拷贝,通俗来讲就是我们常说的复制粘贴,也就是大家用的最多的开发模式,CV开发模式,ctrl+C,ctrl+V开发模式,为什么大家都爱这种开发模式呢,因为开发模式效率极高,如果没有CV功能,哪怕有现成的代码,你也得一行一行抄写,花上的时间也是非常多的,而CV只需要几秒钟的时间,同样的功能,减少了上千倍的时间。
浅拷贝就是我们复制出来的对象与之前的对象是在内存地址对应的还是同一个内存地址,当原对象被更改后,拷贝的对象内容也随之更改。
如上图所示,当对象A浅拷贝出一个对象B后,A的list被修改后,不需要修改对象B,B中的list也会随之修改。实例代码如下
**Person类**
public class Person implements Cloneable{ // 需要实现 Cloneable接口 不然clone方法会报错 List<Integer> list; public Person(List<Integer> list) { this.list = list; } public List<Integer> getList() { return list; } public void setList(List<Integer> list) { this.list = list; } // clone方法 @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } }
测试类
List<Integer> list =new ArrayList<>(); list.add(1); list.add(2); Person person =new Person(list); Person clone = (Person)person.clone(); // 输出 person 与clone 的地址值比较 System.out.println(person.getList()==clone.getList()); // 先输出clone的list值,再修改person的list值 System.out.println("cloneList= " + clone.getList()); list.add(3); person.setList(list); // 修改后的值 System.out.println("cloneList= " + clone.getList()); System.out.println("person = " + person.getList());
结果
true //person 与clone 的地址值比较
cloneList= [1, 2] // person修改前clone list的值
cloneList= [1, 2, 3] // 修改后clone list的值
person = [1, 2, 3] // person的值
严格来说深拷贝才是真正意义上的复制粘贴,我们在网页上复制的东西在本地修改后并不会影响到原有的,同理我们在原有的基础上修改也不会影响到复制后的,原体与拷贝体除了刚开始的值相同外,是两个独立的个体。
深拷贝示意图
如上图所示,当对象A深拷贝出一个对象B后,A的list被修改后,对象B中的list不会随之被修改。要深拷贝一个对象,JDK中常用的方法是序列化为数据流,此方法的前提是对象以及对象中包含的子对象都要继承Serializable接口。实例代码如下
Person类
public class Person implements Cloneable , Serializable { //实现序列化serializable接口 List<Integer> list; public Person(List<Integer> list) { this.list = list; } public List<Integer> getList() { return list; } public void setList(List<Integer> list) { this.list = list; } @Override protected Object clone() throws CloneNotSupportedException { try{ ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(this); ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bis); Person clone = (Person)ois.readObject(); return clone; }catch (Exception e){ e.printStackTrace(); return null; } } }
测试类
List<Integer> list =new ArrayList<>(); list.add(1); list.add(2); Person person =new Person(list); Person clone = (Person)person.clone(); // 输出 person 与clone 的地址值比较 System.out.println(person.getList()==clone.getList()); // 先输出clone的list值,再修改person的list值 System.out.println("cloneList= " + clone.getList()); list.add(3); person.setList(list); // 修改后的值 System.out.println("cloneList= " + clone.getList()); System.out.println("person = " + person.getList());
结果
false//person 与clone 的地址值比较
cloneList= [1, 2] // person修改前clone list的值
cloneList= [1, 2] // 修改后clone list的值
person = [1, 2, 3] // person的值
原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式,是GOF的设计模式之一。
原型模式的目的是 降低实例对象个数 , 减少构造函数的调用次数 ;
1.原型对象实现Cloneable接口
2.原型对象及其成员对象都实现Serializable接口
3.重写clone()方法,采用序列化为数据流进行深拷贝。
在经典框架Spring中也有着原型模式的使用,scope=“prototype”,多实例对象获取的bean就是通过原型模式
// 判断是不是单例. if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { // Explicitly remove instance from singleton cache: It might have been put there // eagerly by the creation process, to allow for circular reference resolution. // Also remove any beans that received a temporary reference to the bean. destroySingleton(beanName); throw ex; } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } // 判断是不是原型对象 else if (mbd.isPrototype()) { // It's a prototype -> create a new instance. Object prototypeInstance = null; try { // 创建原型之前进行回调 beforePrototypeCreation(beanName); // 进入原型对象的创建 prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。