首页 > 代码库 > Java中的深拷贝和浅拷贝 原型模式

Java中的深拷贝和浅拷贝 原型模式

1: Java中浅拷贝和深拷贝的定义:
     浅拷贝:就是指两个对象共同拥有同一个值,一个对象改变了该值,也会影响到另一个对象。
     深拷贝:就是两个对象的值相等,但是互相独立
(深拷贝才是真正的拷贝,浅拷贝只是将引用指向了同一份对象)
2:Java中几种常见的拷贝操作:
(1)“=”操作:也就是赋值操作;
 (2)拷贝构造函数:拷贝构造函数就是构造函数的参数的类型是该构造函数所在的类,即参数就是该类的一个对象。
<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;"> public Clock(Clock clock){
     this.hour=clock.hour;
     this.min=clock.min;
     this.second=clock.second;
    }</span></span></span>
(3)  clone()方法:类实现 Cloneable接口,只是一个标记。

3:几种操作比较

  =
拷贝构造函数
clone方法
预定义非集合类型
int ,Integer,String
1.深拷贝
2.如果支持拷贝构造函数的类型,则是深拷贝
3.不支持
自定义类型
(自定义的一个类)
4.浅拷贝(一个改变,另外一个跟着改变)
5.取决于实现()
 深拷贝
6.  深拷贝
预定义集合类型
7.浅拷贝
8.会逐个调用每个元素的operator=方法
如果add元素是预定义数据类型,则为深拷贝 ;
如果add元素是自定义数据类型,则为 拷贝 ;
9.会逐个调用每个元素的operator=方法 
如果add元素是预定义数据类型,则为深拷贝 ;
如果add元素是自定义数据类型,则为 拷贝 

4:如果一个类实现了clone()方法,并且该类中的成员变量既有基本数据类型(String,int);又有自定义类型的时候,则基本数据类型clone()的是深拷贝,自定义数据类型的是浅拷贝。
<span style="font-size:18px;"><span style="font-size:18px;">package shiyeqiang.resume;

public class ResumeDemo {

 public static void main(String[] args) throws Exception {
		Resume resumeA = new Resume("name A");
		resumeA.setAge(10);
        resumeA.setWorkExperience(1, "百度");
		Resume resumeB = (Resume) resumeA.clone();
		resumeB.setName("name B");
		resumeB.setAge(20);
		resumeB.setWorkExperience(2, "腾讯");
		System.out.println(resumeA);
		System.out.println(resumeB);

	}

}

// 工作经历类
class WorkExperience {

	private int workLong = 0;
	private String company = null;


	public WorkExperience() {

	}

	public int getWorkLong() {
		return workLong;
	}

	public void setWorkLong(int workLong) {
		this.workLong = workLong;
	}

	public String getCompany() {
		return company;
	}

	public void setCompany(String company) {
		this.company = company;
	}

	
}

// 简历类中包括工作经历类以及其他基本数据类型成员
class Resume implements Cloneable {

	private String name = null;
	private int age = 0;
	private WorkExperience workExperience = new WorkExperience();

	public void setWorkExperience(int workLong, String company) {
		this.workExperience.setWorkLong(workLong); // 设置工作时间
		this.workExperience.setCompany(company); // 设置公司
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public Resume(String name) {
		this.name = name;
	}

	public String toString() {
		return "姓名=" + this.name + ",  年龄=" + this.age + ", 工作经历:工作年限="
				+ this.workExperience.getWorkLong() + ", 公司名称="
				+ this.workExperience.getCompany();
	}

	public Object clone() throws CloneNotSupportedException {
		return super.clone();
	}
}
</span></span>
结果显示:
姓名=name A,  年龄=10,工作经历:工作年限=2, 公司名称=腾讯(浅拷贝)
姓名=name B,  年龄=20, 工作经历:工作年限=2, 公司名称=腾讯(浅拷贝)

5:那么一个类要想实现深拷贝应该怎么办呢?
让简历类Resume中引用成员 工作经历WorkExperience类也实现Cloneable接口,并写重写clone()方法;
修改Resume类中的clone方法,在其中必须调用WorkExperience的clone()方法;  
其实说白了,深拷贝,深拷贝啊,也就是一层一层的拷贝,千万别直接用super.clone()方法偷懒哦!
<span style="font-size:18px;"><span style="font-size:18px;">package shiyeqiang.resume;

public class ResumeDemo {

 public static void main(String[] args) throws Exception {
		Resume resumeA = new Resume("name A");
		resumeA.setAge(10);
        resumeA.setWorkExperience(1, "百度");
		Resume resumeB = (Resume) resumeA.clone();
		resumeB.setName("name B");
		resumeB.setAge(20);
		resumeB.setWorkExperience(2, "腾讯");
		System.out.println(resumeA);
		System.out.println(resumeB);

	}

}

// 工作经历类
class WorkExperience implements Cloneable{

	private int workLong = 0;
	private String company = null;


	public WorkExperience() {

	}

	public int getWorkLong() {
		return workLong;
	}

	public void setWorkLong(int workLong) {
		this.workLong = workLong;
	}

	public String getCompany() {
		return company;
	}

	public void setCompany(String company) {
		this.company = company;
	}
    public Object clone() throws CloneNotSupportedException{
    	return super.clone();
    }
	
}

// 简历类中包括工作经历类以及其他基本数据类型成员
class Resume implements Cloneable {

	private String name = null;
	private int age = 0;
	private WorkExperience workExperience = null;

	public void setWorkExperience(int workLong, String company) {
		this.workExperience.setWorkLong(workLong); // 设置工作时间
		this.workExperience.setCompany(company); // 设置公司
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public Resume(String name) {
		this.name = name;
		this.workExperience=new WorkExperience();
	}
	
	<span style="color:#ff0000;">private Resume(WorkExperience workExperience) throws CloneNotSupportedException{
		this.workExperience=(WorkExperience) workExperience.clone();
	}</span>

	public String toString() {
		return "姓名=" + this.name + ",  年龄=" + this.age + ", 工作经历:工作年限="
				+ this.workExperience.getWorkLong() + ", 公司名称="
				+ this.workExperience.getCompany();
	}

	<span style="color:#ff0000;">public Object clone() throws CloneNotSupportedException {
	Resume obj=new Resume(this.workExperience); //调用私有构造函数中的</span><span style="color: rgb(255, 0, 0); background-color: inherit; font-family: Arial; ">workExperience</span><span style="color:#ff0000;">克隆方法
		obj.age=this.age;
		obj.name=name;
		return obj;
	}</span>
}
</span></span>

姓名=name A,  年龄=10, 工作经历:工作年限=1, 公司名称=百度
姓名=name B,  年龄=20, 工作经历:工作年限=2, 公司名称=腾讯