自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

簡單介紹Java克隆對象的特性

開發(fā) 后端
本文主要介紹的是java的對象克隆特性,結(jié)合實(shí)例,分析了克隆的概念和實(shí)現(xiàn)等問題。希望對大家有幫助,一起來看。

java面向?qū)ο蟮木幊坍?dāng)中,要復(fù)制引用類型的對象,就必須克隆對象。通過調(diào)用對所有引用類型和對象都是可用的clone方法,來實(shí)現(xiàn)克隆。

在Java中傳值及引伸深度克隆的思考中,我們講過引申到克隆技術(shù)Java中的所有對象都是Object類的子類。我們知道,Java是純面向?qū)ο蟮某绦蛟O(shè)計(jì)語言。Java里,所有的類的***父類都是java.lang.Object類,也就是說,如果一個(gè)類沒有顯示 申明繼承關(guān)系,它的父類默認(rèn)就是java.lang.Object。

有一個(gè)很簡單的方法可以證明這一點(diǎn),我們寫一個(gè)Test類,如下:

 

  1. public class Test {   
  2. public void someMethod() {   
  3. super.clone();   
  4. }   
  5. }   

 

里面調(diào)用了super.clone(),編譯時(shí)并不報(bào)錯(cuò)。其實(shí)clone()方法為java.lang.Object類提供的一個(gè) protected型方法。

對象克隆

本文通過介紹java.lang.Object#clone()方法來說明Java語言的對象克隆特性。

java.lang.Object#clone()方法由java.lang.Object加以實(shí)現(xiàn),主要對對象本身加以克隆。

首先我們看看下面的例子:

 

  1. public class TestClone {   
  2. public static void main(String[] args) {   
  3. MyClone myClone1 = new MyClone("clone1");   
  4. MyClone myClone2 = (MyClone)myClone1.clone();   
  5. if (myClone2 != null) {   
  6. System.out.println(myClone2.getName());  
  7. System.out.println("myClone2 equals myClone1: " + myClone2.equals(myClone1));   
  8. else {   
  9. System.out.println("Clone Not Supported");   
  10. }   
  11. } }   
  12. class MyClone {   
  13. private String name;   
  14. public MyClone(String name) {   
  15. this.name = name;   
  16. }  
  17. public String getName() {   
  18. return name;   
  19. }   
  20. public void setName(String name) {   
  21. this.name = name; }  
  22. public Object clone() {   
  23. try {  
  24. return super.clone();   
  25. catch (CloneNotSupportedException e) {   
  26. return null;   
  27. }} 

 

編譯執(zhí)行TestClone,打印出:

 

  1. C:\clone>javac *.java   
  2. C:\clone>java TestClone   
  3. Clone Not Supported   
  4. C:\clone>   

 

說明MyClone#clone()方法調(diào)用super.clone()時(shí)拋出了CloneNotSupportedException異常,不支持克隆。

為什么父類java.lang.Object里提供了clone()方法,卻不能調(diào)用呢?

原來,Java語言雖然提供了這個(gè)方法,但考慮到安全問題, 一方面將clone()訪問級別設(shè)置為protected型,以限制外部類訪問;

另一方面,強(qiáng)制需要提供clone功能的子類實(shí)現(xiàn)java.lang.Cloneable接口,在運(yùn)行期,JVM會檢查調(diào)用clone()方法的 類,如果該類未實(shí)現(xiàn)java.lang.Cloneable接口,則拋出CloneNotSupportedException異常。

java.lang.Cloneable接口是一個(gè)空的接口,沒有申明任何屬性與方法。該接口只是告訴JVM,該接口的實(shí)現(xiàn)類需要開放“克隆”功能。

我們再將MyClone類稍作改變,讓其實(shí)現(xiàn)Cloneable接口:

 

  1. class MyClone implements Cloneable {   
  2. ...//其余不做改變   
  3. }   
  4. 編譯執(zhí)行TestClone,打印出:   
  5. C:\clone>javac *.java   
  6. C:\clone>java TestClone   
  7. clone1   
  8. myClone2 equals myClone1: false   
  9. C:\clone>  

 

根據(jù)結(jié)果,我們可以發(fā)現(xiàn):

1,myClone1.clone()克隆了跟myClone1具有相同屬性值的對象

2,但克隆出的對象myClone2跟myClone1不是同一個(gè)對象(具有不同的內(nèi)存空間)

小結(jié)

如果要讓一個(gè)類A提供克隆功能,該類必須實(shí)現(xiàn)java.lang.Cloneable接口,并重載 java.lang.Object#clone()方法。

 

  1. public class A extends Cloneable {   
  2. public Object clone() {   
  3. try {   
  4. return super.clone();   
  5. catch (CloneNotSupportedException e) {   
  6. //throw (new InternalError(e.getMessage()));   
  7. return null;   
  8. }   
  9. }   

 

對象的深層次克隆

上例說明了怎么樣克隆一個(gè)具有簡單屬性(String,int,boolean等)的對象。

但如果一個(gè)對象的屬性類型是List,Map,或者用戶自定義的其他類時(shí),克隆行為是通過怎樣的方式進(jìn)行的?

很多時(shí)候,我們希望即使修改了克隆后的對象的屬性值,也不會影響到原對象,這種克隆我們稱之為對象的深層次克隆。怎么樣實(shí)現(xiàn)對象的深層次克隆呢?

#p#

驗(yàn)證對象的克隆方式

為了驗(yàn)證對象的克隆方式,我們對上面的例子加以改進(jìn),如下(為了節(jié)省篇幅,我們省略了setter與getter方法):

 

  1. public class TestClone {   
  2. public static void main(String[] args) {   
  3. //為克隆對象設(shè)置值   
  4. MyClone myClone1 = new MyClone("clone1");   
  5. myClone1.setBoolValue(true);   
  6. myClone1.setIntValue(100);   
  7. //設(shè)置List值   
  8. List <Element>listValue = new ArrayList<Element>();   
  9. listValue.add(new Element("ListElement1"));   
  10. listValue.add(new Element("ListElement2"));   
  11. listValue.add(new Element("ListElement3"));   
  12. myClone1.setListValue(listValue);   
  13. //設(shè)置Element值   
  14. Element element1 = new Element("element1");   
  15. myClone1.setElement(element1);   
  16. //克隆   
  17. MyClone myClone2 = (MyClone)myClone1.clone();   
  18. if (myClone2 != null) {   
  19. //簡單屬性   
  20. System.out.println("myClone2.name=" + myClone2.getName()   
  21. " myClone2.boolValue=" + myClone2.isBoolValue()   
  22. " myClone2.intValue=" + myClone2.getIntValue() );   
  23. //復(fù)合屬性(List<Element>與Element)   
  24. List clonedList = myClone2.getListValue();   
  25. Element element2 = myClone2.getElement();   
  26. System.out.println("myClone2.listValue.size():" + clonedList.size());   
  27. System.out.println("myClone2.element.equals(myClone1.element):" + element2.equals(element1));   
  28. System.out.println("myClone2.element.name:" + element2.getName());  
  29. //下面我們測試一下myClone2.element是否等于myClone1.element   
  30. //以及myClone2.listValue是否等于myClone1.listValue   
  31. //為此,我們修改myClone2.element與myClone2.listValue,如果myClone1的相應(yīng)值也跟著被修改了,
  32. 則它們引用 的是同一個(gè)內(nèi)存空間的變量,我們認(rèn)為它們相等   
  33. clonedList.add("ListElement4");   
  34. System.out.println("myClone1.listValue.size():" + listValue.size());   
  35. element2.setName("Element2");   
  36. System.out.println("myClone1.element.name:" + element1.getName());   
  37. else {   
  38. System.out.println("Clone Not Supported");   
  39. }   
  40. }   
  41. }   
  42. class MyClone implements Cloneable {   
  43. private int intValue;   
  44. private boolean boolValue;   
  45. private String name;   
  46. private List <Element>listValue;   
  47. private Element element;   
  48. public MyClone(String name) {   
  49. this.name = name;   
  50. }  
  51. ...//setter與getter方法(略)   
  52. }   
  53. class Element implements Cloneable {   
  54. private String name;   
  55. public Element (String name) {   
  56. this.name = name;   
  57. }   
  58. ...//setter與getter方法(略)   
  59. }  

 

編譯執(zhí)行TestClone,打印出:

 

  1. C:\clone>javac *.java   
  2. C:\clone>java TestClone   
  3. myClone2.name=clone1 myClone2.boolValue=true myClone2.intValue=100   
  4. myClone2.listValue.size():3   
  5. myClone2.element.equals(myClone1.element):true   
  6. myClone2.element.name:element1   
  7. myClone1.listValue.size():4   
  8. myClone1.element.name:Element2 09.myClone2 equals myClone1: false 10.C:\clone> 11.  

 

我們發(fā)現(xiàn),對于對象里的List,Element等復(fù)合屬性,super.clone()只是簡單地賦值,沒有采取克隆手段。也就是說,修改被克 隆后的對象值,會影響到原對象。

怎么進(jìn)行深層次的克隆呢?

答案是,我們只能手動在重載的clone()方法里,對屬性也分別采用克隆操作。當(dāng)然條件是,屬性類也得支持克隆操作

 

  1. class MyClone implements Cloneable {   
  2. ...   
  3. public Object clone() {   
  4. try {   
  5. MyClone myClone = (MyClone)super.clone();   
  6. //分別對屬性加以克隆操作   
  7. myClone.element = this.element.clone();   
  8. myClone.listValue = new ArrayList();   
  9. for (Element ele:this.listValue) {   
  10. myClone.listValue.add(ele.clone());   
  11. }   
  12. return myClone;   
  13. catch (CloneNotSupportedException e) {   
  14. return null;   
  15. }   
  16. }   
  17. ...  
  18. }   
  19. //讓Element類也支持克隆操作   
  20. class Element implements Cloneable {   
  21. ...   
  22. public Element clone() {   
  23. try {   
  24. return (Element)super.clone();   
  25. catch (CloneNotSupportedException e) {   
  26. return null;   
  27. }   
  28. }   
  29. }  

 

深層次的克隆操作往往存在效率問題,尤其是需要讓List,Map等集合類也支持深層次的克隆操作時(shí)。

總結(jié)

本文結(jié)合范例,比較深入地介紹了Java語言的克隆屬性,以及克隆的實(shí)現(xiàn)方法等。同時(shí)分析了深層次克隆的概念,實(shí)現(xiàn),以及存在的問題等。 但是有沒有更好的方法呢?當(dāng)然,是有的,串行化來實(shí)現(xiàn)。

【編輯推薦】

  1. 詳細(xì)介紹Java EE開發(fā)四大常用框架
  2. Java 多線程同步問題的探究(一)
  3. Java 多線程同步問題的探究(二)
  4. 談java web server與io形式
  5. JAVA開發(fā) 分析JNI標(biāo)準(zhǔn)原理
責(zé)任編輯:于鐵 來源: 博客園
相關(guān)推薦

2010-10-28 13:06:45

Java克隆特性

2009-09-07 17:46:18

LINQ高級特性

2009-09-09 09:36:25

Linq對象引用

2018-04-03 13:10:27

Java對象克隆

2011-07-04 17:27:42

JSP

2011-05-10 10:00:41

克隆

2012-03-13 16:39:52

Java

2021-04-30 19:53:41

Java表達(dá)式代碼

2009-12-30 14:59:42

ADO.NET數(shù)據(jù)集

2009-08-31 14:54:35

C#對象瀏覽器

2011-07-11 14:19:54

JAVA串口通信

2011-07-04 10:04:52

java網(wǎng)絡(luò)程序

2011-07-11 14:12:19

Java串口通信

2011-06-27 13:17:07

Java EE

2010-03-18 18:20:34

Java Socket

2021-06-03 10:00:47

JavaScript 前端數(shù)克隆對象

2009-06-25 16:52:34

2011-03-11 09:35:01

LAMP介紹

2013-12-12 15:59:23

Lua腳本語言

2010-06-13 15:53:35

ICMP協(xié)議
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號