How to write clone method

 

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 }
给这个方法添加单元测试: public String cloneMessage(CisMonitorData data){ log.info("Starting process to clone and publish message to queue for request id {}", data.getTdsStpId()); CisPubTds cisPubTds = monitorDao.getTdsPubRequestById(data.getTdsStpId()); if(cisPubTds == null){ return CisTStpConstants.MSG_1; } if(cisPubTds.getMessage() == null){ return CisTStpConstants.MSG_2; } if(data.getUser() == null){ return CisTStpConstants.MSG_18; } if(data.getComment() != null && data.getComment().length() > 250){ return CisTStpConstants.MSG_19; } String status = null; try { CisPubTds clonePubTds = (CisPubTds)cisPubTds.clone(); clonePubTds.setTdsStpId(null); clonePubTds.setCreatedDate(new Date()); clonePubTds.setCreatedBy(data.getUser()); clonePubTds.setIsStpEd(0); clonePubTds.setStpEdAt(null); clonePubTds.setUserComment(data.getComment()); clonePubTds = monitorDao.saveOrUpdatePubTds(clonePubTds); if(clonePubTds != null && clonePubTds.getTdsStpId() != null && clonePubTds.getTdsStpId() > 0) { log.info("Updating the XML message for cloned request with new TDS STP id : {}", clonePubTds.getTdsStpId()); /Update tracking ID in SCBML message and save it to database/ Document doc = DocumentUtility.StringToDocument(clonePubTds.getMessage()); DocumentUtility.updateNodeValue(doc, clonePubTds.getTdsStpId()); String updatedXml = DocumentUtility.DocumentToString(doc); clonePubTds.setMessage(updatedXml); clonePubTds = monitorDao.saveOrUpdatePubTds(clonePubTds); /End/ log.info("Update of the XML message for cloned request with new TDS STP id : {} is completed", clonePubTds.getTdsStpId()); log.info("Publishing the cloned message"); boolean statusBool = publish(clonePubTds); if(statusBool){ status = CisTStpConstants.MSG_SUCCESS; } log.info("End of publish with statusBool : {}", statusBool); log.info("End of publish with status : {}", status); }else { status = CisTStpConstants.MSG_8; } log.info("End process to clone and publish message to queue for request id {}", data.getTdsStpId()); } catch (CloneNotSupportedException e) { status = CisTStpConstants.MSG_7; log.error("Error while cloning the object {}", e); } catch (Exception e) { log.error("Error while creating object {}", e); } return status; }
06-07
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值