Java深度拷貝

基本概念

淺拷貝:複製後對象的所有基本類型域的值與原對象相等,所有引用指向的對象和原對象指向的對象相同

深拷貝:複製後對象的所有基本類型的值與原對象相等,且其引用鏈上的所有對象都獲得了一份拷貝

依賴clone方法的深度拷貝

在Java的Object類中有一個clone方法,該方法的行爲由Cloneable接口決定,當某個類實現了Cloneable接口時,Object的clone就返回該對象的逐域拷貝(淺拷貝),否則就會拋出CloneNotSupportedException異常。由於Object類的clone方法的訪問權限爲protected,當一個類實現Cloneable接口時,它不一定具有可訪問的clone方法。爲了使該類型具有適當的、表現良好的clone方法,需要滿足以下幾個條件:

  • 定義一個訪問權限爲public的clone方法
  • 在該clone方法中調用super.clone()  //要求父類的clone表現良好
  • 該類實現Cloneable接口

良好的clone方法通常需要滿足以下約定:

  • x.clone() != x
  • x.clone().getClass() == x.getClass()
  • x.clone().equals(x) == true
class Professor implements Cloneable {
	String name;
	int age;
	public Professor(String name, int age){
		this.name = name;
		this.age = age;
	}
	@Override
	public Professor clone() throws CloneNotSupportedException {
		return (Professor)super.clone();
	}
}
public class Student implements Cloneable {
	String name;
	int age;
	Professor p;
	
	public Student(String name, int age, Professor p){
		this.name = name;
		this.age = age;
		this.p = p;
	}
	@Override
	public Student clone() throws CloneNotSupportedException {
		Student s = (Student)super.clone();
		s.p = this.p.clone();
		return s;
	}
	public static void main(String[] args) throws CloneNotSupportedException{
		Professor p = new Professor("ShunZhongShan", 56);
		Student s = new Student("JiangJieShi", 20, p);
		Student s1 = s.clone();
		System.out.println("Student: name = " + s1.name + " ; age = " + s1.age + "\nProfessor: name = " + s1.p.name + " ; age = " + s1.p.age);
	}
}
運行結果:

Student: name = JiangJieShi ; age = 20
Professor: name = ShunZhongShan ; age = 56

依賴序列化的深度拷貝

另一種實現深度拷貝的方式就是使用序列化,序列化的過程是將對象轉換成數據流;反序列化的過程解析數據流並創建一個新的對象。示例代碼如下:

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

class Professor implements Serializable {
	private static final long serialVersionUID = 252398134512833273L;
	String name;
	int age;
	public Professor(String name, int age){
		this.name = name;
		this.age = age;
	}
}

public class Student implements Serializable {
	private static final long serialVersionUID = 4299622782948980557L;
	String name;
	int age;
	Professor p;
	
	public Student(String name, int age, Professor p){
		this.name = name;
		this.age = age;
		this.p = p;
	}
	
	public Object deepClone() throws IOException, ClassNotFoundException{
		ByteArrayOutputStream bo = new ByteArrayOutputStream();
		ObjectOutputStream os = new ObjectOutputStream(bo);
		os.writeObject(this);
		
		ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
		ObjectInputStream is = new ObjectInputStream(bi);
		return is.readObject();
	}
	
	public static void main(String[] args) throws ClassNotFoundException, IOException{
		Professor p = new Professor("ShunZhongShan", 56);
		Student s = new Student("JiangJieShi", 20, p);
		Student s1 = (Student)s.deepClone();
		System.out.println("Student: name = " + s1.name + " ; age = " + s1.age + "\nProfessor: name = " + s1.p.name + " ; age = " + s1.p.age);
	}
}
運行結果爲:
Student: name = JiangJieShi ; age = 20
Professor: name = ShunZhongShan ; age = 5
發佈了65 篇原創文章 · 獲贊 6 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章