Java對象複製

1.Java對象複製概念

    1.1 淺複製(淺克隆)

        複製的對象的全部變量與含有與原來的對象相同的值,而全部的對其餘對象的引用仍然指向原對象。換言之,淺複製僅僅複製所考慮的對象,而不復制它所引用的對象。java

    1.2 深複製(深度克隆)

        複製的對象的全部變量都含有與原來的對象相同的值,除去那些引用其餘對象的變量。那些引用其餘對象的變量將指向複製的新對象,而不是原來的對象。換言之,深複製把要複製的對象所引用的對象都複製了一遍。jvm

2.Java對象的clone()克隆方法

    2.1 clone方法

    clone方法將對象複製了一份並返回給調用者。通常而言,clone()方法知足ide

  • 對任何的對象x,都有x.clone() != x;也即克隆的對象與原對象不是同一個對象,他們有不一樣的內存地址
  • 對任何的對象x,都有x.clone().getClass() == x.getClass(),也即克隆對象與原對象的類型一致。
  • 若是對象x的equals()方法定義恰當,那麼x.clone().equal(x)應該成立。

    2.2 Java中對象的克隆

  • 爲了獲取對象的一份拷貝,咱們能夠利用Object的clone()方法
  • 在派生類中覆蓋基類的clone()方法,並聲明爲public
  • 在派生類的clone()方法中,調用super.clone()。
  • 在派生類中實現Cloneable接口

    2.3 示例

    2.3.1 淺複製示例

package org.wem.im;

/**
 * 
 * <p>
 * Title: Person<br>
 * Copyright: Copyright (c) 2016<br>
 * Company: <br>
 * </p>
 *
 * <p>
 * Description: 測試Java對象淺克隆
 * </p>
 *
 * @version v1.0.0
 * @author kucs
 * @date 2016年9月30日下午2:28:22
 *
 * Modification History:
 *---------------------------------------------------------*
 *
 */
public class Person implements Cloneable {
	class Worker{
		private String workName;
		private String department;
		public String getWorkName() {
			return workName;
		}
		public void setWorkName(String workName) {
			this.workName = workName;
		}
		public String getDepartment() {
			return department;
		}
		public void setDepartment(String department) {
			this.department = department;
		}
		@Override
		public String toString() {
			return "Worker [workName=" + workName + ", department=" + department + "]";
		}
		
	}
	private String name;
	private String age;
	private String weight;
	private String height;
	private Worker worker;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getAge() {
		return age;
	}
	public void setAge(String age) {
		this.age = age;
	}
	public String getWeight() {
		return weight;
	}
	public void setWeight(String weight) {
		this.weight = weight;
	}
	public String getHeight() {
		return height;
	}
	public void setHeight(String height) {
		this.height = height;
	}
	
	public Worker getWorker() {
		return worker;
	}
	public void setWorker(Worker worker) {
		this.worker = worker;
	}
	@Override
	protected Object clone() throws CloneNotSupportedException {
		// TODO Auto-generated method stub
		return super.clone();
	}
	
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", weight=" + weight + ", height=" + height + ", worker="
				+ worker + "]";
	}
	public static void main(String[] args) throws CloneNotSupportedException {
		Person p = new Person();
		Worker worker = p.new Worker();
		worker.setWorkName("asiainfo");
		worker.setDepartment("cboss");
		p.setWorker(worker);
		p.setName("kucs");
		p.setAge("24");
		p.setWeight("65");
		p.setHeight("170");
		Person p_clone = (Person) p.clone();
		System.out.println("原對象信息:"+p.toString());
		System.out.println("克隆對象信息:"+p_clone.toString());
		//修改p_clone對象的值
		p_clone.setName("kucs_clone");
		//修改對象引用的對象的值
		worker.setWorkName("asianinfo_clone");
		System.out.println("修改後的克隆對象信息:"+p_clone.toString());
		System.out.println("原對象信息:"+p.toString());
		if(p.getWorker().getWorkName().equals(p_clone.getWorker().getWorkName())){
			System.out.println("淺複製對象,其引用的對象未複製");
		}else{
			System.out.println("非淺複製對象,其引用的對象也複製");
		}
	}
}

運行結果測試

原對象信息:Person [name=kucs, age=24, weight=65, height=170, worker=Worker [workName=asiainfo, department=cboss]]
克隆對象信息:Person [name=kucs, age=24, weight=65, height=170, worker=Worker [workName=asiainfo, department=cboss]]
修改後的克隆對象信息:Person [name=kucs_clone, age=24, weight=65, height=170, worker=Worker [workName=asianinfo_clone, department=cboss]]
原對象信息:Person [name=kucs, age=24, weight=65, height=170, worker=Worker [workName=asianinfo_clone, department=cboss]]
淺複製對象,其引用的對象未複製

結果說明:淺克隆以後的對象與原對象不是同一個對象。修改其中一個對象的值對另外一個對象沒有影響。this

                淺克隆中其引用的對象未複製,仍是指向同一個對象。spa

    2.3.2 深複製示例

        對淺複製示例代碼作了調整code

package org.wem.im;

/**
 * 
 * <p>
 * Title: Person<br>
 * Copyright: Copyright (c) 2016<br>
 * Company: <br>
 * </p>
 *
 * <p>
 * Description: 測試Java對象深度克隆
 * </p>
 *
 * @version v1.0.0
 * @author kucs
 * @date 2016年9月30日下午2:45:22
 *
 * Modification History:
 *---------------------------------------------------------*
 *
 */
public class Person implements Cloneable {
	class Worker implements Cloneable{
		private String workName;
		private String department;
		public String getWorkName() {
			return workName;
		}
		public void setWorkName(String workName) {
			this.workName = workName;
		}
		public String getDepartment() {
			return department;
		}
		public void setDepartment(String department) {
			this.department = department;
		}
		
		@Override
		protected Object clone() throws CloneNotSupportedException {
			// TODO Auto-generated method stub
			return super.clone();
		}
		@Override
		public String toString() {
			return "Worker [workName=" + workName + ", department=" + department + "]";
		}
		
	}
	private String name;
	private String age;
	private String weight;
	private String height;
	private Worker worker;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getAge() {
		return age;
	}
	public void setAge(String age) {
		this.age = age;
	}
	public String getWeight() {
		return weight;
	}
	public void setWeight(String weight) {
		this.weight = weight;
	}
	public String getHeight() {
		return height;
	}
	public void setHeight(String height) {
		this.height = height;
	}
	
	public Worker getWorker() {
		return worker;
	}
	public void setWorker(Worker worker) {
		this.worker = worker;
	}
	@Override
	protected Object clone() throws CloneNotSupportedException {
		// TODO Auto-generated method stub
		Person p = (Person) super.clone();
		p.worker = (Worker) worker.clone();
		return p;
	}
	
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", weight=" + weight + ", height=" + height + ", worker="
				+ worker + "]";
	}
	public static void main(String[] args) throws CloneNotSupportedException {
		Person p = new Person();
		Worker worker = p.new Worker();
		worker.setWorkName("asiainfo");
		worker.setDepartment("cboss");
		p.setWorker(worker);
		p.setName("kucs");
		p.setAge("24");
		p.setWeight("65");
		p.setHeight("170");
		Person p_clone = (Person) p.clone();
		System.out.println("原對象信息:"+p.toString());
		System.out.println("克隆對象信息:"+p_clone.toString());
		//修改p_clone對象的值
		p_clone.setName("kucs_clone");
		//修改對象引用的對象的值
		worker.setWorkName("asianinfo_clone");
		System.out.println("修改後的克隆對象信息:"+p_clone.toString());
		System.out.println("原對象信息:"+p.toString());
		if(p.getWorker().getWorkName().equals(p_clone.getWorker().getWorkName())){
			System.out.println("淺複製對象,其引用的對象未複製");
		}else{
			System.out.println("非淺複製對象,其引用的對象也複製");
		}
	}
}

    運行結果:對象

原對象信息:Person [name=kucs, age=24, weight=65, height=170, worker=Worker [workName=asiainfo, department=cboss]]
克隆對象信息:Person [name=kucs, age=24, weight=65, height=170, worker=Worker [workName=asiainfo, department=cboss]]
修改後的克隆對象信息:Person [name=kucs_clone, age=24, weight=65, height=170, worker=Worker [workName=asiainfo, department=cboss]]
原對象信息:Person [name=kucs, age=24, weight=65, height=170, worker=Worker [workName=asianinfo_clone, department=cboss]]
非淺複製對象,其引用的對象也複製

    結果說明:深克隆中,對克隆後的對象修改值,不影響原對象的值。修改克隆後的對象引用的值,對原對象引用的對象也沒有影響。接口

3.利用串行化來作深複製ip

    這主要是爲了不重寫比較複雜的深複製clone()方法。把對象寫到流裏的過程是串行化過程(Serialization),把對象從流中讀取出來是並行化(Deserialization)過程。

    注意:寫在流裏的對象時一個拷貝,而原對象仍然存在jvm中,所以串行化過程只是一個對象的拷貝。

    在Java語言中,深複製一個對象,經常能夠先使用對象實現Serializable接口,而後把對象寫到一個流裏,再從流裏讀取出來,即可以重建對象。

package org.wem.im;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

/**
 * 
 * <p>
 * Title: Person<br>
 * Copyright: Copyright (c) 2016<br>
 * Company: <br>
 * </p>
 *
 * <p>
 * Description: 測試Java對象克隆
 * </p>
 *
 * @version v1.0.0
 * @author kucs
 * @date 2016年9月30日下午2:28:22
 *
 * Modification History:
 *---------------------------------------------------------*
 *
 */
public class Person implements Serializable {
	class Worker implements Serializable{
		private String workName;
		private String department;
		public String getWorkName() {
			return workName;
		}
		public void setWorkName(String workName) {
			this.workName = workName;
		}
		public String getDepartment() {
			return department;
		}
		public void setDepartment(String department) {
			this.department = department;
		}
		
		@Override
		public String toString() {
			return "Worker [workName=" + workName + ", department=" + department + "]";
		}
		
	}
	private String name;
	private String age;
	private String weight;
	private String height;
	private Worker worker;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getAge() {
		return age;
	}
	public void setAge(String age) {
		this.age = age;
	}
	public String getWeight() {
		return weight;
	}
	public void setWeight(String weight) {
		this.weight = weight;
	}
	public String getHeight() {
		return height;
	}
	public void setHeight(String height) {
		this.height = height;
	}
	
	public Worker getWorker() {
		return worker;
	}
	public void setWorker(Worker worker) {
		this.worker = worker;
	}
	public Object deepClone() throws IOException, 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
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", weight=" + weight + ", height=" + height + ", worker="
				+ worker + "]";
	}
	public static void main(String[] args) throws CloneNotSupportedException, ClassNotFoundException, IOException {
		Person p = new Person();
		Worker worker = p.new Worker();
		worker.setWorkName("asiainfo");
		worker.setDepartment("cboss");
		p.setWorker(worker);
		p.setName("kucs");
		p.setAge("24");
		p.setWeight("65");
		p.setHeight("170");
		Person p_clone = (Person) p.deepClone();
		System.out.println("原對象信息:"+p.toString());
		System.out.println("克隆對象信息:"+p_clone.toString());
		//修改p_clone對象的值
		p_clone.setName("kucs_clone");
		//修改對象引用的對象的值
		worker.setWorkName("asianinfo_clone");
		System.out.println("修改後的克隆對象信息:"+p_clone.toString());
		System.out.println("原對象信息:"+p.toString());
		if(p.getWorker().getWorkName().equals(p_clone.getWorker().getWorkName())){
			System.out.println("淺複製對象,其引用的對象未複製");
		}else{
			System.out.println("非淺複製對象,其引用的對象也複製");
		}
	}
}

運行結果

原對象信息:Person [name=kucs, age=24, weight=65, height=170, worker=Worker [workName=asiainfo, department=cboss]]
克隆對象信息:Person [name=kucs, age=24, weight=65, height=170, worker=Worker [workName=asiainfo, department=cboss]]
修改後的克隆對象信息:Person [name=kucs_clone, age=24, weight=65, height=170, worker=Worker [workName=asiainfo, department=cboss]]
原對象信息:Person [name=kucs, age=24, weight=65, height=170, worker=Worker [workName=asianinfo_clone, department=cboss]]
非淺複製對象,其引用的對象也複製
相關文章
相關標籤/搜索