java中的clone()方法

Why Clone 
Suppose you have an object ‘a’ of class ‘A’. Sometimes you may need another new object ‘b’. It also belongs to class ‘A’ and has the same data with object ‘a’. But if you do some modification on b, it has no effect to the value of ‘a’. We call this process which produced new object ‘b’ as clone object ‘a’. The commonest time that you need to clone an object is when it is a parameter or return value of one of your public methods. If it is a parameter that you save somewhere, then you don't want the caller to be able to modify it later. So you save a copy of the object. Likewise, if you are returning an object that is part of your class's internal state, you need to return a copy instead so that callers can't accidentally or deliberately change that internal state. 

Conventions of clone 
1. x.clone() !=  x                                                 // x.clone() will return a new object 
2. x.clone().equals(x)                                          // this is the meaning of ‘copy’ 
3. x.clone().getClass() == x.getClass() 
4. The object returned by clone method should be independent of the object (which is  
    being cloned). 

These are not absolute requirements but are general intends of clone method which is also recommended in Java Documents. 

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? 

                        v       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. 

                        v       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: 

                              class A implements Cloneable 
                              class B extends A implements Cloneable { 

                                                        public Object clone() throws CloneNotSupportedException{ 
                                                                B b = null; 
       
                                                                b = (B) super.clone();  // It seems that super.clone() is   

                                                                                                //A.clone(), so it will return an 

                                                                                                 //object of Class A. This is incorrect. 

                                                                                                 //If the clone method of class A calls 

                                                                                                 //super.clone method too, it will 

                                                                                                //return a new object belongs to 

                                                                                                //class B. Thus, we can cast it to 

                                                                                                //class B. This is the benefit of 

                                                                                                //Object.clone(). 
                                                                return b; 
                                                } 
                                        } 
                                        Now, let’s consider another case, if we write clone method of class A like this: 

                                        class A { 
                                                public Object clone() { 
                                                A a = null; 
                                                a = new A(); 
                                                // Then do some copy data operation. 
                                                         return a; 
                                        } 
                                        } 
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 
/** 
* class B support clone 
* @author xzhu2 

*/ 
class B implements Cloneable { 
        private int intMember; 
       
        public B(int i) { 
                intMember = i; 
        } 
       
        public void setIntMember(int i) { 
                intMember = i; 
        } 
       
        public Object clone() 
                 throws CloneNotSupportedException { 
                B clonedObject = null; 
               
                // Firstly, call super.clone to return new object 
                clonedObject = (B)super.clone(); 
               
                // Secondly, clone member here 
                clonedObject.setIntMember(intMember); 
               
                // The end, return new object 
                return clonedObject; 
        } 


/** 
* class C doesn't support clone 
* @author xzhu2 

*/ 
class C { 
        private int intMember; 
       
        public C(int i) { 
                intMember = i; 
        } 
       
        public void setIntMember(int i) { 
                intMember = i; 
        } 
       
        public int getIntMember() { 
                return intMember; 
        } 


class A implements Cloneable { 
        private int intMember = 0; 
        private String stringMember = ""; 
        private B supportCloneMember = null; 
        private C notSupportCloneMember = null; 
       
        public void setIntMember(int i) { 
                intMember = i; 
        } 
       
        public void setStringMember(String s) { 
                stringMember = s; 
        } 
       
        public void setB(B b) { 
                supportCloneMember = b; 
        } 
       
        public void setC(C c) { 
                notSupportCloneMember = c; 
        } 
       
        public Object clone() 
                throws CloneNotSupportedException { 
                A clonedObject = null; 

                // Firstly, call super.clone to return new object 
                clonedObject = (A)super.clone(); 

                // Secondly, clone members here 
               
                // For basic type member, directly set it to clonedObject      
                // Because basic type parameter passes value. Modify 
                // clonedObject.intMember can not effect the intMember 
                // of itself. 
                clonedObject.setIntMember(intMember); 
                // For immutable member, directly set it to clonedObject. 
                // Becasue we can not change the value of immutable 
            // variable once it was setted. 
                clonedObject.setStringMember(stringMember); 
                // For member which support clone, we just clone it and 
                // set the return object to the member of new object. 
                B clonedB = (B)supportCloneMember.clone(); 
                clonedObject.setB(clonedB); 
                // For member which do not support clone, we need to create 
                // new object. 
                C clonedC = new C(notSupportCloneMember.getIntMember()); 
                clonedObject.setC(clonedC); 
               
                // The end, return new object 
                return clonedObject; 
        } 
}
Javaclone()方法Object定义的方法,它用于创建并返回当前对象的一个副本。这个副本就是一个新的对象,它与原始对象具有相同的属性和方法。通常情况下,我们需要在一个类实现clone()方法来支持对象的克隆。 克隆对象是在Java处理对象的一种常见方式。通过克隆,我们可以在不修改原始对象的情况下创建该对象的一个副本。这在某些情况下是非常有用的,例如在多线程环境下,我们需要多个线程同时访问同一个对象,但是又不希望它们之间相互干扰。 在Java,要使用clone()方法来实现对象的克隆,我们需要满足两个条件: 1. 实现Cloneable接口:这个接口是一个标记接口,它没有任何方法,只是用来标记一个类可以被克隆。 2. 重写clone()方法:这个方法Object的一个protected方法,需要在我们的类进行重写。在重写这个方法时,我们需要调用super.clone()方法来创建一个新的对象,并将原始对象的属性复制到这个新对象。 下面是一个示例代码,演示了如何在Java实现对象的克隆: ``` public class MyClass implements Cloneable { private int value; public MyClass(int value) { this.value = value; } public int getValue() { return value; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } ``` 在这个示例代码,我们实现了一个MyClass类,并重写了clone()方法。在这个方法,我们调用了super.clone()方法来创建一个新的对象,并返回这个新对象。由于我们的类实现了Cloneable接口,因此它可以被克隆。 使用这个类进行克隆的代码如下: ``` MyClass obj1 = new MyClass(10); MyClass obj2 = (MyClass) obj1.clone(); System.out.println(obj1.getValue()); // 输出10 System.out.println(obj2.getValue()); // 输出10 ``` 在这个代码,我们创建了一个MyClass对象obj1,并将其克隆为obj2。由于这两个对象具有相同的属性和方法,因此它们的输出结果也是相同的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值