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;
}
}
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;
}
}
发表评论
-
转:深入理解java的finalize
2012-08-09 15:14 994目录 基本预备相关知识 对象的销毁过程 对象重生的例子 对象的 ... -
转:java 垃圾收集器的使用技巧
2012-08-09 14:54 602垃圾收集器(Garbage Collect ... -
转:你知道的java和你不知的的java
2012-08-09 13:23 693最近我们收到一封电子邮件,咨询 “什么是Java?”条目的信息 ... -
转:你知道的java和你不知的的java
2012-08-09 13:23 0最近我们收到一封电子邮件,咨询 “什么是Java?”条目的信息 ... -
你知道的java和你不知的的java
2012-08-09 13:22 0最近我们收到一封电子邮件,咨询 “什么是Java?”条目的信息 ...
相关推荐
在Java编程语言中,`clone()`方法是一个非常重要的概念,特别是在对象复制和克隆方面。这个小例子将帮助初学者理解如何在Java中使用`clone()`来创建对象的副本。让我们深入探讨`clone()`方法以及它在实际编程中的...
详细的描述了Java中 clone方法使用
Java中的`clone`方法是Java语言提供的一种复制对象的方式,它允许创建一个对象的副本,这个副本与原对象具有相同的属性值,但它们是两个独立的对象,修改副本不会影响原对象。`clone`方法存在于Java的`java.lang....
Java Clone 深拷贝与浅拷贝的两种实现方法 Java Clone 是 Java 语言中的一种复制对象的机制,它可以将一个对象的所有属性和状态复制到另一个对象中,实现对象的深拷贝和浅拷贝。下面我们将讨论 Java 中的深拷贝和浅...
在Java编程语言中,`Clone`机制是一种对象复制的方式,允许创建一个现有对象的副本。在Java中,对象的默认复制是浅复制(shallow copy),这意味着只复制对象本身,而不复制它引用的对象。要实现深复制(deep copy)...
### Java中的`clone`方法详解:浅拷贝与深拷贝 #### 一、引言 在Java中,`clone`方法提供了一种快速复制对象的方式。它属于`Object`类的一部分,但需要显式地在子类中声明并实现`Cloneable`接口才能正常使用。本文...
在Java编程语言中,`clone`是一个非常重要的概念,它涉及到对象复制和对象的深拷贝与浅拷贝。本文将深入探讨Java中的`clone`方法及其相关知识点。 首先,`clone`方法是Java `Object`类的一个成员方法,定义为`...
Java中的`clone`方法是Java语言提供的一种复制对象的机制,它允许创建一个现有对象的副本,这个副本具有与原始对象相同的状态,但它们是独立的实体,对其中一个对象的修改不会影响另一个。`clone`方法是Java `Object...
Java中的clone方法详解_动力节点Java学院,动力节点口口相传的Java黄埔军校
在Java编程语言中,克隆(Clone)机制是一种创建对象副本的方法,它允许开发者创建一个已有对象的新实例,这个新实例与原对象具有相同的属性值,但却是两个独立的对象,彼此的操作不会互相影响。克隆机制在某些情况...
在Java编程语言中,`clone()`方法是一个非常重要的概念,特别是在处理对象复制和克隆时。这个方法源自`Object`类,是所有Java类的基类。`clone()`的使用通常涉及到深度复制和浅复制的概念,这两者在数据结构和内存...
Java中的clone方法详解 在Java语言中,clone方法是一个非常重要的概念,它允许对象被复制,从而创造出一个新的对象。下面我们将详细介绍Java中的clone方法,并讨论它的实现机制和应用场景。 什么是clone方法 ...
Java 中 clone() 的使用方法 Java 中的 clone() 方法是对象的复制方法,其主要作用是创建一个与原对象相同的新对象。下面将详细介绍 Java 中 clone() 方法的使用方法。 什么是 clone() 方法? clone() 方法是 ...
在Java编程语言中,`Cloneable`接口和`clone()`方法是两个重要的概念,它们用于对象复制。在本文中,我们将深入探讨Java中的浅克隆(shallow clone)和深克隆(deep clone),并结合测试代码进行分析。 首先,让...
Java中的对象创建主要有两种方式,即使用`new`操作符创建新对象以及通过`clone`方法复制已有对象。本文将从JVM的角度深入探讨Java的`clone`操作,揭示其工作原理及其潜在的问题。 首先,让我们理解`clone`方法的...
clone的用法 希望有帮助,仅供参考 通过例子的分析,可以对克隆的方法有所深入了解
并且由于Java不能通过简单的赋值来解决对象复制的问题,在开发过程中,也常常要要应用clone()方法来复制对象。比如函数参数类型是自定义的类时,此时便是引用传递而不是值传递。以下是一个小例子: ...