日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網營銷解決方案
簡述Java語言的對象克隆特性

在Java中傳值及引伸深度克隆的思考中,我們講過引申到克隆技術Java中的所有對象都是Object類的子類。我們知道,Java是純面向對象的程序設計語言。Java里,所有的類的***父類都是java.lang.Object類,也就是說,如果一個類沒有顯示 申明繼承關系,它的父類默認就是java.lang.Object。

有一個很簡單的方法可以證明這一點,我們寫一個Test類,如下:

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

里面調用了super.clone(),編譯時并不報錯。其實clone()方法為java.lang.Object類提供的一個 protected型方法。

對象克隆

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

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

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

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

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

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

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

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

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

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

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

我們再將MyClone類稍作改變,讓其實現Cloneable接口:

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

根據結果,我們可以發(fā)現:

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

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

小結

如果要讓一個類A提供克隆功能,該類必須實現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.     } 

對象的深層次克隆

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

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

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

驗證對象的克隆方式

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

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

編譯執(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 
  9. myClone2 equals myClone1: false 
  10. C:\clone> 

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

怎么進行深層次的克隆呢?

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

 
 
 
  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.             
  9.              myClone.listValue = new ArrayList(); 
  10.             for (Element ele:this.listValue) { 
  11.                  myClone.listValue.add(ele.clone()); 
  12.              } 
  13.                         
  14.             return myClone; 
  15.          } catch (CloneNotSupportedException e) { 
  16.             return null; 
  17.          } 
  18.      } 
  19.      ... 
  20. //讓Element類也支持克隆操作 
  21. class Element implements Cloneable   { 
  22.      ... 
  23.     public Element clone() { 
  24.         try { 
  25.             return (Element)super.clone(); 
  26.          } catch (CloneNotSupportedException e) { 
  27.             return null; 
  28.          } 
  29.      } 

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

總結

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


網頁標題:簡述Java語言的對象克隆特性
標題網址:http://www.5511xx.com/article/copjois.html