How to write clone method

          Posted on 2010-04-21 10:51 祝嘉 閱讀(378) 評論(0)  編輯  收藏 所屬分類: JavaSE

          By convention, the approach of writing clone method is:

          1. Implements Cloneable interface

          This approach ensures your clone method can directly or indirectly call Object.clone(). Otherwise, calling Object.clone() will throws CloneNotSupportedException. Why we need to call Object.clone() in our clone method? Please see approach 2.2.

          2. Override the clone method

          2.1 Make the clone method to public method

          Please be noted that the clone method type of Object class is: protected Object clone() throws CloneNotSupportedException In order to support other class can use our clone method, we should define it as public method.

          2.2 Call super.clone() to produce the new object

          By convention, the object returned by clone method should be obtained by calling super.clone (this means it’s better to produce the new object by super.clone() than directly use “new” operator). If a class and all of its superclasses (except Object) obey this convention, it will be the case that x.clone().getClass() == x.getClass().

          Key point: why we should use super.clone() to produce the new object instead of directly use “new” operator?

          First of all, if all classes obey this convention, our clone method will directly or indirectly call Object.clone method. This method is a native method, it will be more efficient than directly “new” an object.

          Secondly, Object.clone method can recognize the class type which called the clone method using RTTI mechanism. And it will return the new object which has the correct class type.

          For example:

           1 class A implements Cloneable
           2 class B extends A implements Cloneable {
           3 
           4     public Object clone() throws CloneNotSupportedException {
           5         B b = null;
           6 
           7         b = (B) super.clone(); // It seems that super.clone() is
           8                                            // A.clone(), so it will return an
           9                                            // object of Class A. This is incorrect.
          10                                           // If the clone method of class A calls
          11                                           // super.clone method too, it will
          12                                           // return a new object belongs to
          13                                           // class B. Thus, we can cast it to
          14                                           // class B. This is the benefit of
          15                                           // Object.clone().
          16         return b;
          17     }
          18 }

          Now, let’s consider another case, if we write clone method of class A like this:

          1 class A {
          2     public Object clone() {
          3         A a = null;
          4         a = new A();
          5         // Then do some copy data operation.
          6         return a;
          7    }
          8 }

          When B.clone() calls super.clone(),unfortunately we can only get the object whose class is A. And we can’t cast the new object to class B since B is a subclass of A.

          That’s why it’s strongly recommended that clone method of all classes obey the convention that obtained the new object by calling super.clone().

          2.3 Clone members

          There are two cases: If the member supports clone, it’s better to call the clone method of the member to return a copy object of this member. If the member doesn’t support clone, you should create a new object which is the copy of the member. After this approach, it will be ensured that x.clone.equals(x) and x.clone() is independent with x.

          Examples:

            1 /**
            2  * class B support clone
            3  * 
            4  */
            5 class B implements Cloneable {
            6     private int intMember;
            7 
            8     public B(int i) {
            9         intMember = i;
           10     }
           11 
           12     public void setIntMember(int i) {
           13         intMember = i;
           14     }
           15 
           16     public Object clone() throws CloneNotSupportedException {
           17         B clonedObject = null;
           18 
           19         // Firstly, call super.clone to return new object
           20         clonedObject = (B) super.clone();
           21 
           22         // Secondly, clone member here
           23         clonedObject.setIntMember(intMember);
           24 
           25         // The end, return new object
           26         return clonedObject;
           27     }
           28 }
           29 
           30 /**
           31  * class C doesn't support clone
           32  * 
           33  */
           34 class C {
           35     private int intMember;
           36 
           37     public C(int i) {
           38         intMember = i;
           39     }
           40 
           41     public void setIntMember(int i) {
           42         intMember = i;
           43     }
           44 
           45     public int getIntMember() {
           46         return intMember;
           47     }
           48 }
           49 
           50 class A implements Cloneable {
           51     private int intMember = 0;
           52     private String stringMember = "";
           53     private B supportCloneMember = null;
           54     private C notSupportCloneMember = null;
           55 
           56     public void setIntMember(int i) {
           57         intMember = i;
           58     }
           59 
           60     public void setStringMember(String s) {
           61         stringMember = s;
           62     }
           63 
           64     public void setB(B b) {
           65         supportCloneMember = b;
           66     }
           67 
           68     public void setC(C c) {
           69         notSupportCloneMember = c;
           70     }
           71 
           72     public Object clone() throws CloneNotSupportedException {
           73         A clonedObject = null;
           74 
           75         // Firstly, call super.clone to return new object
           76         clonedObject = (A) super.clone();
           77 
           78         // Secondly, clone members here
           79 
           80         // For basic type member, directly set it to clonedObject
           81         // Because basic type parameter passes value. Modify
           82         // clonedObject.intMember can not effect the intMember
           83         // of itself.
           84         clonedObject.setIntMember(intMember);
           85         // For immutable member, directly set it to clonedObject.
           86         // Becasue we can not change the value of immutable
           87         // variable once it was setted.
           88         clonedObject.setStringMember(stringMember);
           89         // For member which support clone, we just clone it and
           90         // set the return object to the member of new object.
           91         B clonedB = (B) supportCloneMember.clone();
           92         clonedObject.setB(clonedB);
           93         // For member which do not support clone, we need to create
           94         // new object.
           95         C clonedC = new C(notSupportCloneMember.getIntMember());
           96         clonedObject.setC(clonedC);
           97 
           98         // The end, return new object
           99         return clonedObject;
          100     }
          101 }


          主站蜘蛛池模板: 和平区| 图木舒克市| 河源市| 博白县| 承德市| 九寨沟县| 安龙县| 黄平县| 双辽市| 浦县| 长岛县| 龙里县| 剑河县| 炎陵县| 共和县| 黔南| 泽州县| 顺平县| 东乡县| 衡山县| 鄂尔多斯市| 青州市| 宽城| 青铜峡市| 斗六市| 皮山县| 张家港市| 绥滨县| 和平区| 班戈县| 屏山县| 东安县| 温泉县| 锡林郭勒盟| 江孜县| 长武县| 阳谷县| 凤冈县| 兰州市| 乐东| 河东区|