一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

探討java深拷貝

2020-03-31 11:43楚巖 JAVA教程

這篇文章主要針對(duì)java深拷貝的相關(guān)內(nèi)容進(jìn)行解析,幫助大家學(xué)習(xí)理解java深拷貝,感興趣的小伙伴們可以參考一下

本文將討論以下4個(gè)問(wèn)題

    1. java Cloneable接口實(shí)現(xiàn)深拷貝
    2. java 序列化實(shí)現(xiàn)深拷貝
    3. 號(hào)稱最快的深拷貝二方庫(kù)cloning源碼分析
    4. 幾種拷貝方式速度的比較

深拷貝的概念本文就不說(shuō)了。在C++中實(shí)現(xiàn)深拷貝一般情況下重載賦值操作符 “=” 來(lái)實(shí)現(xiàn)同一個(gè)類的對(duì)象間的深拷貝,所以很自然的在java中我們也同樣可以定義一個(gè)copy函數(shù),在函數(shù)內(nèi)部為對(duì)象的每一個(gè)屬性作賦值操作。這種方式簡(jiǎn)單自然,但存在一個(gè)致命性的問(wèn)題:如果有一天在類中新增加了一個(gè)需要深拷貝的屬性,那么相應(yīng)的copy函數(shù)也得進(jìn)行修改,這種方法給類的可擴(kuò)展性帶來(lái)了極大的不方便。怎么解決這種問(wèn)題,且看接下來(lái)的1、2、3章節(jié)的實(shí)現(xiàn)方式和4節(jié)的速度測(cè)試。
1. java Cloneable接口實(shí)現(xiàn)深拷貝
這種方式,需要類實(shí)現(xiàn)Colneable接口 clone 函數(shù),在clone函數(shù)中調(diào)用super.clone。這種方式的深拷貝同樣會(huì)帶來(lái)另一個(gè)問(wèn)題,如果類中有其他類的對(duì)象作為屬性,則其他的類也需要重載并實(shí)現(xiàn)Cloneable接口。來(lái)一個(gè)例子,在下例中ComplexDO中包含了SimpleDO對(duì)象,要實(shí)現(xiàn)ComplexDO深拷貝,則需要先實(shí)現(xiàn)SimpleDO的clone接口:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class SimpleDO implements Cloneable, Serializable {
    private int x = 1;
    private String s = "simpleDO";
 
    @Override
    protected Object clone() throws CloneNotSupportedException {
      SimpleDO newClass = (SimpleDO)super.clone();
      return newClass;
    }
  }
 
  public class ComplexDO implements Cloneable, Serializable {
    private int x = 1;
    private String s = "complex";
    private Integer a = 123;
    private Integer b = 1234;
    private Integer c = 1334455;
    private String s2 = "hehehe";
    private String s3 = "hahahaha";
    private Long id = 1233245L;
    private ArrayList<SimpleDO> l = new ArrayList<SimpleDO>();
 
    @Override
    public Object clone() throws CloneNotSupportedException {
      ComplexDO newClass = (ComplexDO) super.clone();
      newClass.l = new ArrayList<SimpleDO>();
      for (SimpleDO simple : this.l) {
        newClass.l.add((SimpleDO) simple.clone());
      }
      return newClass;
    }
  }

需要注意的是很多文章說(shuō)String類型的對(duì)象賦值操作符是深拷貝,但是其實(shí)在java中使用賦值操作符的都屬于淺拷貝,但為什么這么明顯的錯(cuò)誤這么多的文章會(huì)非要說(shuō)這個(gè)是深拷貝呢?我的理解是String、類型的屬性都是基本類型,而且提供的方法只要是設(shè)計(jì)到內(nèi)部數(shù)據(jù)的變動(dòng)都會(huì)new一個(gè)新的對(duì)象出來(lái)。所以一個(gè)String的操作不會(huì)影響到其原先指向的內(nèi)存。所以一般說(shuō)String等基礎(chǔ)類的賦值操作為深拷貝。
由于這個(gè)原因,在使用String字符串拼接的時(shí)候,需要開(kāi)辟新的內(nèi)存,所以很多人建議用StringBuilder來(lái)代替String來(lái)做拼接,因?yàn)镾tringBuilder只有在內(nèi)置的char數(shù)組范圍不夠的時(shí)候才重新申請(qǐng)更大的內(nèi)存(對(duì)于現(xiàn)代JVM,會(huì)對(duì)代碼調(diào)優(yōu),String+String會(huì)被優(yōu)化成StringBuilder.append的相類似的指令)。與拼接相對(duì)的裁剪,在String有個(gè)subString函數(shù),當(dāng)使用subString函數(shù)時(shí),新String的內(nèi)部char數(shù)組和原String是否相同?這個(gè)比較有意思,感興趣的可以對(duì)比看看JDK1.6和JKD1.7的實(shí)現(xiàn)。
2. java 序列化實(shí)現(xiàn)深拷貝
這種方式的原理是利用java序列化,將一個(gè)對(duì)象序列化成二進(jìn)制字節(jié)流,然后對(duì)該字節(jié)流反序列化賦值給一個(gè)對(duì)象。代碼示例:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public Object seirCopy(Object src) {
   try {
     ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
     ObjectOutputStream out = new ObjectOutputStream(byteOut);
     out.writeObject(src);
 
     ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
     ObjectInputStream in = new ObjectInputStream(byteIn);
     Object dest = in.readObject();
     return dest;
   } catch (Exception e) {
     //do some error handler
     return null;
   }
}

當(dāng)然,也可以選用json等序列化的庫(kù)來(lái)完成序列化,這種方式有效的規(guī)避了Cloneabel接口的可擴(kuò)展缺點(diǎn),一個(gè)函數(shù)就可以基本上適用于所有的類.缺點(diǎn)是相對(duì)內(nèi)存拷貝,序列化需要先將對(duì)象轉(zhuǎn)換成二進(jìn)制字節(jié)流,然后反序列化將該二進(jìn)制字節(jié)流重新拷貝到一塊對(duì)象內(nèi)存,相對(duì)慢點(diǎn)。
3. 號(hào)稱最快的深拷貝二方庫(kù)cloning源碼分析
在源碼中,核心的處理邏輯在Cloner類中,
分兩條遞歸鏈路:

  • (1)deepClone->cloneInternal->fastClone->cloneInternal
  • (2)deepClone->cloneInternal->cloneObject->cloneInternal

在(1)中fastClone完成的是繼承自IfastCloner接口類的對(duì)象,即都是些集合操作的拷貝;
在(2)中cloneObject完成的是通過(guò)反射機(jī)制拿到普通對(duì)象的每一個(gè)屬性,然后對(duì)使用Objenesis新生成對(duì)象的屬性賦值。
這種方式可擴(kuò)展性強(qiáng),不僅可以依靠其現(xiàn)有的代碼完成深拷貝,還可以自己定義一些克隆的方式和不需要克隆的類型,靈活性強(qiáng)。
4. 幾種拷貝方式速度的比較
上述3中模式都可以完成深拷貝,那種拷貝的方式速度最快是我們所關(guān)心的。
先上測(cè)試代碼:
 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public void testCloneComplex() throws CloneNotSupportedException {
  final int copyCount = 1;
  List<ComplexDO> complexDOList = new ArrayList<ComplexDO>(copyCount * 3);
  final ComplexDO complex = new ComplexDO();
 
  //調(diào)用二方庫(kù)
  long start = System.currentTimeMillis();
  for(int i = 0; i < copyCount; ++i) {
    final ComplexDO deepClone = cloner.deepClone(complex);
    complexDOList.add(deepClone);
  }
  long end = System.currentTimeMillis();
  System.out.println("deepClone cost time=" + (end-start));
 
  //調(diào)用Cloneable接口實(shí)現(xiàn)的clone函數(shù)
  start = System.currentTimeMillis();
  for(int i = 0; i < copyCount; ++i) {
    final ComplexDO interfaceClone = (ComplexDO) complex.clone();
    complexDOList.add(interfaceClone);
  }
  end = System.currentTimeMillis();
  System.out.println("interfaceClone cost time=" + (end-start));
 
  //序列化與反序列化生成新對(duì)象
  start = System.currentTimeMillis();
  for(int i = 0; i < copyCount; ++i) {
    final ComplexDO seirClone = seirCopy(complex);
    complexDOList.add(seirClone);
  }
  end = System.currentTimeMillis();
  System.out.println("seirClone cost time=" + (end-start));
}

探討java深拷貝

運(yùn)行結(jié)果的單位為毫秒(此數(shù)據(jù)忽略不計(jì)算java熱點(diǎn)和可能的gc)。

從這個(gè)表可以得出結(jié)論:

1、實(shí)現(xiàn)Cloneable接口的拷貝是最快的,因?yàn)樗簧婕暗搅藘?nèi)存拷貝,但是如果涉及的屬性為普通對(duì)象比較多的時(shí)候?qū)懫饋?lái)麻煩點(diǎn)
2、序列化/反序列化拷貝最慢
3、使用cloning庫(kù),由于使用了遞歸和反射機(jī)制相對(duì)Cloneable接口實(shí)現(xiàn)的拷貝要慢,但比序列化方式要快。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 99久久精品国产片久人 | daring国家队在线观看樱花动漫 | 青草欧美| 2020年国产精品午夜福利在线观看 | 亚洲色图欧美色 | 精品久久久久中文字幕日本 | 日韩精品视频在线播放 | 日韩国产成人精品视频 | 青青草国产免费久久久91 | 午夜影院0606 | 男女拍拍拍免费视频网站 | 男人看的网址 | 欧美大陆日韩一区二区三区 | 亚洲黄网站wwwwww | 国产区香蕉精品系列在线观看不卡 | 公园吃女人奶野战视频 | 热99精品只有里视频最新 | 小柔的性放荡羞辱日记 | 欧美黑人性 | 九九国产在线观看 | 俄罗斯妈妈k8影院在线观看 | 亚洲精品91香蕉综合区 | 好姑娘完整版在线观看中文 | 欧美性xxxxx| 亚洲国产第一区二区三区 | 国产三级跑 | 精品一久久香蕉国产二月 | 亚洲高清毛片一区二区 | 国产亚洲精品第一综合linode | 国产一级在线观看视频 | 国产精品va在线观看手机版 | 91日本在线观看亚洲精品 | 日本精品久久久久久久久免费 | 韩国办公室激情 | 1919gogo女厕盗摄 | 91国内精品久久久久影院优播 | 国产精品99久久免费观看 | 97热| 日韩精选 | 日本不卡不码高清免费观看 | 99自拍网 |