java深度克隆_Java深入学习26:Java深度克隆
Java深入學(xué)習(xí)26:Java深度克隆
深克隆和淺克隆區(qū)別
淺克隆: 只copy對(duì)象引用,不copy對(duì)象本身。即對(duì)象地址不變,仍然只存在一個(gè)對(duì)象。
深克隆: 不僅拷貝對(duì)象本身,而且拷貝對(duì)象包含的引用指向的所有對(duì)象。
深克隆的兩個(gè)方案
方案1——實(shí)現(xiàn)Cloneable接口,重寫Object類地?clone()方法
分如下三步
1. 對(duì)象的類實(shí)現(xiàn)Cloneable接口(必須,否則會(huì)拋出CloneNotSupportedException異常);
2. 覆蓋Object類的clone()方法 (覆蓋clone()方法,將訪問修飾符改為public,默認(rèn)是protected);
3. 在clone()方法中調(diào)用super.clone();
public classCloneTest {public static void main(String[] args) throwsCloneNotSupportedException {
Student stu= new Student("A");
Student deep= stu.clone();//深克隆
Student shallow = stu;//淺克隆
shallow.setName("B");
System.out.println("original: " + stu);//Student{name='B'}
System.out.println("deep: " + deep);//Student{name='A'}
System.out.println("shallow: " + shallow);//Student{name='B'}
}
}class Student implementsCloneable{privateString name;publicStudent(String name) {this.name =name;
}publicString getName() {returnname;
}public voidsetName(String name) {this.name =name;
}
@Overridepublic Student clone() throws CloneNotSupportedException {
return (Student) super.clone();
}
@OverridepublicString toString() {return "Student{" +
"name='" + name + '\'' +
'}';
}
}
深克隆的多級(jí)深克隆問題:
重寫clone()方法,只會(huì)深克隆類和類中所有非基本數(shù)據(jù)類型的屬性對(duì)應(yīng)的類。對(duì)于類中的屬性對(duì)應(yīng)的類,是無法深克隆的,如果深克隆類中的屬性對(duì)應(yīng)的類,需要額外的調(diào)用類中的屬性對(duì)應(yīng)的類clone方法
public classCloneTest {public static void main(String[] args) throwsCloneNotSupportedException {
School sch= new School("a",new Student("A"));
School deepSch= sch.clone();//深克隆
School shallowSch = sch;//淺克隆
shallowSch.getStu().setName("B");
System.out.println(sch);//School{name='a', stu=Student{name='B'}}
System.out.println(deepSch);//School{name='a', stu=Student{name='A'}}
System.out.println(shallowSch);//School{name='a', stu=Student{name='B'}}
}
}class School implementsCloneable{privateString name;privateStudent stu;
@Overridepublic School clone() throwsCloneNotSupportedException {//return (School)super.clone();//該方法無法深克隆Sch中的Student
School clone = (School) super.clone();
clone.setStu(this.stu.clone());returnclone;
}publicSchool(String name, Student stu) {this.name =name;this.stu =stu;
}publicString getName() {returnname;
}public voidsetName(String name) {this.name =name;
}publicStudent getStu() {returnstu;
}public voidsetStu(Student stu) {this.stu =stu;
}
@OverridepublicString toString() {return "School{" +
"name='" + name + '\'' +
", stu=" + stu +
'}';
}
}
方案2——序列化深克隆
什么是序列化?
1- java序列化是指把java對(duì)象轉(zhuǎn)換為字節(jié)序列的過程,而java反序列化是指把字節(jié)序列恢復(fù)為java對(duì)象的過程
2- 序列化:對(duì)象序列化的最主要的用處就是在傳遞和保存對(duì)象的時(shí)候,保證對(duì)象的完整性和可傳遞性。序列化是把對(duì)象轉(zhuǎn)換成有序字節(jié)流,以便在網(wǎng)絡(luò)上傳輸或者保存在本地文件中。序列化后的字節(jié)流保存的java對(duì)象的狀態(tài)以及相關(guān)的描述信息。序列化機(jī)制的核心作用就是對(duì)象狀態(tài)的保存與重建。
3- 反序列化:客戶端從文件中或網(wǎng)絡(luò)上獲得序列化后的對(duì)象字節(jié)流后,根據(jù)字節(jié)流中所保存的對(duì)象狀態(tài)及描述信息,通過反序列化重建對(duì)象。
4- 序列化就是把實(shí)體對(duì)象狀態(tài)按照一定的格式寫入到有序字節(jié)流,反序列化就是從有序字節(jié)流重建對(duì)象,恢復(fù)對(duì)象狀態(tài)
import java.io.*;public classSerializeDeepCloneTest {public static voidmain(String[] args) {
SchoolSeri sch= new SchoolSeri("zjut",new StudentSeri("tyj"));
SchoolSeri schSeri= null;
System.out.println(sch);try{
schSeri=SerializeDeepCloneUtil.deepClone(sch);
System.out.println(sch);
}catch(Exception e) {
e.printStackTrace();
}
System.out.println(sch==schSeri);
}
}classSerializeDeepCloneUtil{//序列化深克隆
static T deepClone(T obj){if(obj ==null){return null;
}
T cloneObj= null;//序列化
ByteArrayOutputStream bout = null;
ObjectOutputStream oos= null;try{//創(chuàng)建字節(jié)數(shù)組輸出流//new ByteArrayOutputStream() Creates a new byte array output stream.
bout = newByteArrayOutputStream();//創(chuàng)建對(duì)象輸出流//new ObjectOutputStream(OutputStream out): Creates an ObjectOutputStream that writes to the specified OutputStream.
oos = newObjectOutputStream(bout);//向?qū)ο筝敵隽髦袑憯?shù)據(jù)//void writeObject(Object obj): Write the specified object to the ObjectOutputStream.
oos.writeObject(obj);
}catch(IOException e) {
e.printStackTrace();
}finally{
close(oos);
close(bout);
}//反序列化
ByteArrayInputStream bin = null;
ObjectInputStream ois= null;try{//創(chuàng)建字節(jié)數(shù)組輸入流//new ByteArrayInputStream(byte buf[]): Creates a ByteArrayInputStream so that it uses buf as its buffer array.
bin = newByteArrayInputStream(bout.toByteArray());//創(chuàng)建對(duì)象輸入流//new ObjectInputStream(InputStream in): Creates an ObjectInputStream that reads from the specified InputStream.
ois = newObjectInputStream(bin);//從對(duì)象輸入流中讀取數(shù)據(jù)//Object readObject(): Read an object from the ObjectInputStream.
cloneObj =(T)ois.readObject();
}catch (IOException |ClassNotFoundException e) {
e.printStackTrace();
}finally{
close(ois);
close(bin);
}returncloneObj;
}//關(guān)閉流
private static voidclose(Closeable closeable){if(closeable != null){try{
closeable.close();
}catch(IOException e) {
e.printStackTrace();
}
}
}
}
public class SchoolSeri implementsSerializable{privateString name;privateStudentSeri stu;publicSchoolSeri(String name, StudentSeri stu) {this.name =name;this.stu =stu;
}publicString getName() {returnname;
}public voidsetName(String name) {this.name =name;
}publicStudentSeri getStu() {returnstu;
}public voidsetStu(StudentSeri stu) {this.stu =stu;
}
@OverridepublicString toString() {return "School{" +
"name='" + name + '\'' +
", stu=" + stu +
'}';
}
}public class StudentSeri implementsSerializable{privateString name;publicStudentSeri(String name) {this.name =name;
}publicString getName() {returnname;
}public voidsetName(String name) {this.name =name;
}
@OverridepublicString toString() {return "Student{" +
"name='" + name + '\'' +
'}';
}
}
END
總結(jié)
以上是生活随笔為你收集整理的java深度克隆_Java深入学习26:Java深度克隆的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java akka_Akka系列(九):
- 下一篇: java提取word中的文字_Java