默认浅拷贝
如果使用clone()方法想要实现深拷贝 必须在实体类中每一个其他内部类对象中实现Cloneable接口,并且重写clone方法
如下:
觉得麻烦可以读到流里再读出来:
package com.fwz.tproject;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OptionalDataException;
import java.io.Serializable;
import org.junit.Test;
import lombok.Data;
public class CloneTest1 implements Serializable {
@Data
public class Person implements Serializable, Cloneable {
/**
*
*/
private static final long serialVersionUID = 1L;
private String name;
private Integer age;
private Address address;
public Object deepClone() throws IOException, OptionalDataException, ClassNotFoundException {
// 将对象写到流里
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream oo = new ObjectOutputStream(bo);
oo.writeObject(this);
// 从流里读出来
ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
ObjectInputStream oi = new ObjectInputStream(bi);
return (oi.readObject());
}
@Override
protected Object clone() throws CloneNotSupportedException {
Person p = (Person) super.clone();
p.address = (Address) p.address.clone();
return p;
}
}
@Data
public class Address implements Serializable, Cloneable {
/**
*
*/
private static final long serialVersionUID = 1L;
private String type;
private String value;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
@Test
public void testShallowCopy() throws Exception {
Address address = new Address();
address.setType("Home");
address.setValue("北京");
Person p1 = new Person();
p1.setAge(31);
p1.setName("Peter");
p1.setAddress(address);
Person p2 = (Person) p1.deepClone();
System.out.println(p1 == p2);// false
p2.setAge(44);
p2.getAddress().setType("Office");
System.out.println("p1=" + p1);
System.out.println("p2=" + p2);
}
@Test
public void testShallowCopy2() throws Exception {
Address address = new Address();
address.setType("Home");
address.setValue("北京");
Person p1 = new Person();
p1.setAge(31);
p1.setName("Peter");
p1.setAddress(address);
Person p2 = (Person) p1.clone();
System.out.println(p1 == p2);// false
p2.setAge(44);
p2.getAddress().setType("Office");
System.out.println("p1=" + p1);
System.out.println("p2=" + p2);
}
}
输出:
false p1=CloneTest1.Person(name=Peter, age=31, address=CloneTest1.Address(type=Home, value=北京)) p2=CloneTest1.Person(name=Peter, age=44, address=CloneTest1.Address(type=Office, value=北京))
原型模式的应用场景
Spring 中bean 的scope 属性的声明:
<bean id="student" class="com.Student" scope="prototype"/>
spring 默认scope 是单例模式,这样只会创建一个Action对象,每次访问都是同一个Action对象,数据不安全,struts2 是要求每次次访问都对应不同的Action,scope="prototype" 可以保证 当有请求的时候 都创建一个Action对象。
public class ProtoType {
public static void main(String[] args) {
// TODO Auto-generated method stub
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
// 获取monster[通过id获取monster]
Object bean = applicationContext.getBean("student");
System.out.println("bean:" + bean);
Object bean2 = applicationContext.getBean("student");
System.out.println("bean1" + bean2);
System.out.println(bean == bean2);
}
}
```
运行结果
bean:com.atguigu.spring.bean.Student@52bf72b5
bean1com.atguigu.spring.bean.Student@37afeb11
false