深入淺出了解面向對象的深克隆和淺克隆
閱讀本文需要一定的面向對象基礎和JavaIO流的相應知識!
深克隆(要實作深克隆被克隆類以及被克隆類的引用必須實作Serializable接口)
(未實作接口會抛出NotSerializableException異常)
定義:被複制對象的所有變量都含有與原來的對象相同的值,除去那些引用其他對象的變量。那些引用其他對象的變量将指向被複制過的新對象,而不再是原有的那些被引用的對象。深克隆的是實作實際上是對對象的序列化和反序列化
淺克隆(要實作淺克隆被克隆的類必須實作Cloneable接口)
(未實作接口會跑出CloneNotSupportedException異常)
定義:被複制對象的所有變量都含有與原來的對象相同的值,而所有的對其他對象的引用仍然指向原來的對象。
詳細講解代及實作碼如下
實作類:
package com.xiaoqiang;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
/**
* 本案例配合上文解說
* 詳細講解java深克隆淺克隆的差別
* @author xiaoqiang
* @Time 2017年5月5日
*/
public class Student implements Cloneable,Serializable{
private String name;
private int age;
private Date birthday;
public Student(){
super();
}
public Student(String name, int age, Date birthday) {
super();
this.name = name;
this.age = age;
this.birthday = birthday;
}
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 Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", birthday="
+ birthday + "]";
}
/**
* 完成淺克隆類需實作Cloneable接口
* @param student
* @return Object
*/
public Object shallowClone(Student student){
try {
return student.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
/**
* 完成深克隆被克隆的類和類的引用類
* 均實作Serializable接口
* @param student
* @return Object
*/
public Object deepClone(Student student){
/*
*本次實作深克隆使用 ByteArrayOutputStream
* 和ByteArrayInputStream
*作為複制過程中字元數組存儲中介
*/
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos =null;
ObjectInputStream ois = null;
try {
//将bos作為收集位元組數組中介
oos= new ObjectOutputStream(bos);
//将傳入參數student類寫入bos中
oos.writeObject(student);
//将讀取到資料傳入ObjectInputStream
ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
return ois.readObject();
} catch (IOException | ClassNotFoundException e) {
//JDK 1.7後引入 可以同時用| 優化代碼可讀性
e.printStackTrace();
return null;
} finally{
try {
bos.close();
oos.close();
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Student student = new Student("小強",,new Date("1997","06","13"));
System.out.println("原student類 "+student);
//淺克隆對象shallowCloneStudent
Student shallowCloneStudent = (Student) student.shallowClone(student);
System.out.println("淺克隆出來的student "+shallowCloneStudent);
System.out.println("淺克隆和深克隆對象對比 "+shallowCloneStudent.equals(student));
System.out.println("淺克隆Date和深克隆Date類引用是否相同 "+shallowCloneStudent.getBirthday().equals(student.getBirthday()));
//深克隆對象deepCloneStudent
Student deepCloneStudent = (Student) student.deepClone(student);
System.out.println("深克隆出來的student "+deepCloneStudent);
System.out.println("深克隆和深克隆對象對比 "+deepCloneStudent.equals(student));
System.out.println("深克隆Date和深克隆Date類引用是否相同 "+deepCloneStudent.getBirthday().equals(student.getBirthday()));
}
}
引用類
package com.xiaoqiang;
import java.io.Serializable;
/**
* @author xiaoqiang
* @Time 2017年5月5日
*/
public class Date implements Serializable{
private String year;
private String month;
private String day;
public Date(){}
public Date(String year, String month, String date) {
super();
this.year = year;
this.month = month;
this.day = date;
}
public String getYear() {
return year;
}
public void setYear(String year) {
this.year = year;
}
public String getMonth() {
return month;
}
public void setMonth(String month) {
this.month = month;
}
public String getDate() {
return day;
}
public void setDate(String date) {
this.day = date;
}
@Override
public String toString() {
return year+"年"+month+"月"+day+"日";
}
}