java clone 浅拷贝 和 深拷贝

默认浅拷贝

如果使用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
posted @ 2021-01-31 13:41  陈扬天  阅读(312)  评论(0编辑  收藏  举报