首頁  >  文章  >  Java  >  java序列化存取實現物件克隆的實例詳解

java序列化存取實現物件克隆的實例詳解

Y2J
Y2J原創
2017-04-26 10:05:301238瀏覽

本篇文章是對序列化訪問實現java物件深度克隆的方法進行了詳細的分析介紹,需要的朋友參考下

我們知道,在java中,將一個非原型類型類型的物件引用,賦值給另一個物件的引用之後,這兩個引用就指向了同一個對象,如:

 程式碼如下:

public class DeepCloneTest { private class CloneTest {  private Long myLong = new Long(1); } public static void main(String args[]) {  new DeepCloneTest().Test(); } public void Test() {  CloneTest ct1 = new CloneTest();  CloneTest ct2 = ct1;  // to see if ct1 and ct2 are one same reference.  System.out.println("ct1: " + ct1);  System.out.println("ct2: " + ct2);  // if ct1 and ct2 point to one same object, then ct1.myLong == ct2.myLong.  System.out.println("ct1.myLong: " + ct1.myLong);  System.out.println("ct2.myLong: " + ct2.myLong);  // we change ct2's myLong  ct2.myLong = 2L;  // to see whether ct1's myLong was changed.  System.out.println("ct1.myLong: " + ct1.myLong);  System.out.println("ct2.myLong: " + ct2.myLong); }}

out put:
ct1: DeepCloneTest$CloneTest@c17164
ct2: DeepCloneTest$CloneTest@c17164
ct1.myLong: 1
ct2.myLong: 1
ct1.myLong: 2
ct2.myLong: #2.
這個很easy,估計學java的都知道(不知道的是學java的麼?)。
在記憶體中,物件的參考存放在堆疊中,物件的數據,存放在堆中,堆疊中的參考指向了堆中的物件。這裡就是兩個堆疊中的引用,指向了堆中的同一個對象,所以,當改變了ct2 的myLong,可以看到,ct1 的myLong 值也隨之改變,如果用圖來表示,就很容易理解了:

java序列化存取實現物件克隆的實例詳解

左邊的是堆疊區,該區中有兩個引用,值相同,它們指向了右邊堆區的同一個對象。
大多時候,我們會用 java 語言的這一特性做我們想做的事情,比如,將物件的引用作為入參傳入一個方法中,在方法中,對引用所指物件做相應修改。但有時,我們希望建構出一個和已經存在的對象具有完全相同的內容,但引用不同的對象,為此,可以這樣做

 代碼如下:

public class DeepCloneTest{ // must implements Cloneable. private class CloneTest implements Cloneable{  private Object o = new Object();  public CloneTest clone() {   CloneTest ct = null;   try {    ct = (CloneTest)super.clone();   } catch (CloneNotSupportedException e) {    e.printStackTrace();   }   return ct;  } } public static void main(String args[]) {  new DeepCloneTest().Test(); } public void Test() {  CloneTest ct1 = new CloneTest();  CloneTest ct2 = ct1.clone();  // to see if ct1 and ct2 are one same reference.  System.out.println("ct1: " + ct1);  System.out.println("ct2: " + ct2);  // whether ct1.o == ct2.o ? yes  System.out.println("ct1.o " + ct1.o);  System.out.println("ct1.o " + ct1.o); }}

out put:
ct1: DeepCloneTest$CloneTest@c17164
ct2: DeepCloneTest$CloneTest@1fb8ee3
ct1.o java.lang.Object@61de33
1.o java .lang.Object@61de33
從輸出可以看出:ct1 和ct2 確實是兩個不同的引用,所以我們想當然的認為,ct1.o 和ct2.o 也是兩個不同的物件了,但從輸出可以看出並非如此! ct1.o 和 ct2.o 是同一個物件!原因在於,雖然用到了克隆,上面只是淺度克隆,用圖形來表示:

java序列化存取實現物件克隆的實例詳解
看到上面的 o 了麼?其實是兩個物件共享的。這就相當於,你本來有一個羊圈1,裡面有一隻羊,然後你又弄了一個羊圈2,在不將羊從羊圈1裡牽出來的情況下,將羊也圈在了羊圈2中,你以為你有兩隻羊了,其實呢?大家都知道。

這就是淺度克隆的結果:如果你想讓兩個物件有獨立的 o,就必須再對 o 做複製運算。可能有些人認為這沒有什麼,做就做唄,但想過沒有,如果不止一個 o, 還有很多很多的類似 o 的東東,你都逐一去做克隆嗎?顯然是不太現實的。

一種解決方法是:將物件先序列化儲存到流中,然後再從留中讀出對象,這樣就可以保證讀取出來的資料和之前的對象,裡面的數值完全相同,就像是完全的拷貝。

 程式碼如下:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class DeepCloneTest {
 // must implements Cloneable.
 private class CloneTest implements Serializable{
  private static final long serialVersionUID = 1L;
  private Object o = new Object();
  public CloneTest deepClone() {
   CloneTest ct = null;
   try {
    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
             ObjectOutputStream oos = new ObjectOutputStream(baos); 
             oos.writeObject(this);
             ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); 
             ObjectInputStream ois= new ObjectInputStream(bais); 
             ct = (CloneTest)ois.readObject(); 
   } catch (IOException e) {
    e.printStackTrace();
   } catch (ClassNotFoundException e) {
    e.printStackTrace();
   }
   return ct;
  }
 }
 public static void main(String args[]) {
  new DeepCloneTest().Test();
 }
 public void Test() {
  CloneTest ct1 = new CloneTest();
  CloneTest ct2 = ct1.deepClone();
  // to see if ct1 and ct2 are one same reference.
  System.out.println("ct1: " + ct1);
  System.out.println("ct2: " + ct2);
  // whether ct1.o == ct2.o ? no
  System.out.println("ct1.o " + ct1.o);
  System.out.println("ct1.o " + ct1.o);
 }
}


這個時候,記憶體中的資料就是這樣的了:

java序列化存取實現物件克隆的實例詳解

##克隆任務完成。

以上是java序列化存取實現物件克隆的實例詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn