欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于序列化存取實(shí)現(xiàn)java對(duì)象深度克隆的方法詳解

 更新時(shí)間:2013年05月17日 10:19:09   作者:  
本篇文章是對(duì)序列化存取實(shí)現(xiàn)java對(duì)象深度克隆的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
我們知道,在java中,將一個(gè)非原型類型類型的對(duì)象引用,賦值給另一個(gè)對(duì)象的引用之后,這兩個(gè)引用就指向了同一個(gè)對(duì)象,如:
復(fù)制代碼 代碼如下:

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
這個(gè)很easy,估計(jì)學(xué)java的都知道(不知道的是學(xué)java的么?)。
在內(nèi)存中,對(duì)象的引用存放在棧中,對(duì)象的數(shù)據(jù),存放在堆中,棧中的引用指向了堆中的對(duì)象。這里就是兩個(gè)棧中的引用,指向了堆中的同一個(gè)對(duì)象,所以,當(dāng)改變了 ct2 的 myLong,可以看到,ct1 的 myLong 值也隨之改變,如果用圖來表示,就很容易理解了:


左邊的是棧區(qū),該區(qū)中有兩個(gè)引用,值相同,它們指向了右邊堆區(qū)的同一個(gè)對(duì)象。
大多時(shí)候,我們會(huì)用 java 語言的這一特性做我們想做的事情,比如,將對(duì)象的引用作為入?yún)魅胍粋€(gè)方法中,在方法中,對(duì)引用所指對(duì)象做相應(yīng)修改。但有時(shí),我們希望構(gòu)造出一個(gè)和已經(jīng)存在的對(duì)象具有完全相同的內(nèi)容,但引用不同的對(duì)象,為此,可以這樣做
復(fù)制代碼 代碼如下:

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
ct1.o java.lang.Object@61de33
從輸出可以看出:ct1 和 ct2 確實(shí)是兩個(gè)不同的引用,所以我們想當(dāng)然的認(rèn)為,ct1.o 和 ct2.o 也是兩個(gè)不同的對(duì)象了,但從輸出可以看出并非如此!ct1.o 和 ct2.o 是同一個(gè)對(duì)象!原因在于,雖然用到了克隆,但上面只是淺度克隆,用圖形來表示:


看到上面的 o 了么?其實(shí)是兩個(gè)對(duì)象共享的。這就相當(dāng)于,你本來有一個(gè)羊圈1,里面有一只羊,然后你又弄了一個(gè)羊圈2,在不將羊從羊圈1里牽出來的情況下,將羊也圈在了羊圈2中,你以為你有兩條羊了,其實(shí)呢?大家都知道。

這就是淺度克隆的結(jié)果:如果你想讓兩個(gè)對(duì)象具有獨(dú)立的 o,就必須再對(duì) o 做克隆操作??赡苡行┤苏J(rèn)為這沒有什么,做就做唄,但想過沒有,如果不止一個(gè) o, 還有很多很多的類似 o 的東東,你都逐一去做克隆嗎?顯然是不太現(xiàn)實(shí)的。

一種解決方法是:將對(duì)象先序列化存儲(chǔ)到流中,然后再從留中讀出對(duì)象,這樣就可以保證讀取出來的數(shù)據(jù)和之前的對(duì)象,里面的值完全相同,就像是一個(gè)完全的拷貝。
復(fù)制代碼 代碼如下:

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);
 }
}

這個(gè)時(shí)候,內(nèi)存中的數(shù)據(jù)就是這樣的了:


克隆任務(wù)完成。

相關(guān)文章

  • java 關(guān)鍵字static詳細(xì)介紹及如何使用

    java 關(guān)鍵字static詳細(xì)介紹及如何使用

    這篇文章主要介紹了java 關(guān)鍵字static詳細(xì)介紹及如何使用的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • Java內(nèi)置GUI Frame類的使用

    Java內(nèi)置GUI Frame類的使用

    這篇文章主要介紹了Java內(nèi)置GUI Frame類的使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • Mybatis引入與使用的圖文步驟

    Mybatis引入與使用的圖文步驟

    本文主要介紹了Mybatis引入與使用的圖文步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-09-09
  • SpringBoot?DataSource數(shù)據(jù)源實(shí)現(xiàn)自動(dòng)配置流程詳解

    SpringBoot?DataSource數(shù)據(jù)源實(shí)現(xiàn)自動(dòng)配置流程詳解

    這篇文章主要介紹了SpringBoot?DataSource數(shù)據(jù)源實(shí)現(xiàn)自動(dòng)配置流程,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-10-10
  • java實(shí)現(xiàn)字符串匹配求兩個(gè)字符串的最大公共子串

    java實(shí)現(xiàn)字符串匹配求兩個(gè)字符串的最大公共子串

    這篇文章主要介紹了java實(shí)現(xiàn)求兩個(gè)字符串最大公共子串的方法,詳細(xì)的描述了兩個(gè)字符串的最大公共子串算法的實(shí)現(xiàn),需要的朋友可以參考下
    2016-10-10
  • 如何使用Spring AOP的通知類型及創(chuàng)建通知

    如何使用Spring AOP的通知類型及創(chuàng)建通知

    這篇文章主要給大家介紹了關(guān)于如何使用Spring AOP的通知類型及創(chuàng)建通知的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Spring AOP具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • Spring?Boot詳解五種實(shí)現(xiàn)跨域的方式

    Spring?Boot詳解五種實(shí)現(xiàn)跨域的方式

    跨域指的是瀏覽器不能執(zhí)?其他?站的腳本。它是由瀏覽器的同源策略造成的,是瀏覽器對(duì)javascript施加的安全限制,這篇文章主要介紹了springboot實(shí)現(xiàn)跨域的5種方式,需要的朋友可以參考下
    2022-06-06
  • java中數(shù)組的相關(guān)知識(shí)小結(jié)(推薦)

    java中數(shù)組的相關(guān)知識(shí)小結(jié)(推薦)

    下面小編就為大家?guī)硪黄猨ava中數(shù)組的相關(guān)知識(shí)小結(jié)(推薦)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-07-07
  • springcloud本地調(diào)試feign調(diào)用出現(xiàn)的詭異404問題及解決

    springcloud本地調(diào)試feign調(diào)用出現(xiàn)的詭異404問題及解決

    這篇文章主要介紹了springcloud本地調(diào)試feign調(diào)用出現(xiàn)的詭異404問題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Spring Security OAuth2 授權(quán)碼模式的實(shí)現(xiàn)

    Spring Security OAuth2 授權(quán)碼模式的實(shí)現(xiàn)

    這篇文章主要介紹了Spring Security OAuth2 授權(quán)碼模式的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08

最新評(píng)論