Detailed description of the clone method in Java

Source: Internet
Author: User

Create an object in Java
As the name implies, clone is replication. in Java, the clone method is called by an object, so the object will be copied. To copy an object, you must first allocate a space of the same size as the source object and create a new object in the space. How can I create objects in java?
1. Use the new operator to create an object 2. Use the clone method to copy an object
So what are the similarities and differences between the two methods? The new operator is intended to allocate memory. When the program executes the new operator, it first looks at the type behind the new operator. Only by knowing the type can we know how much memory space to allocate. After the memory is allocated, call the constructor to fill in the various fields of the object. This step is called object initialization. After the constructor returns, an object is created, you can publish his reference (Address) to the outside, and you can use this reference to manipulate this object externally. In the first step, clone is similar to new in allocating memory. When the clone method is called, the allocated memory and source object (that is, the object that calls the clone method) are the same, then, use the corresponding fields in the original object to fill in the fields of the new object. After the filling is complete, the clone method returns, and a new identical object is created, you can also publish the reference of this new object to the external.


Copy object or copy reference
In Java, the following code is very common:

Person p = new Person(23, "zhang");Person p1 = p;System.out.println(p);System.out.println(p1);

When Person p1 = p; is a new object created after execution? First, check the printed result: com. pansoft. zhangjg. testclone. Person @ 2f9ee1ac
Com. pansoft. zhangjg. testclone. Person @ 2f9ee1ac

As you can see, the printed Address values are the same. Since the addresses are the same, they must be the same object. P and p1 are just references. They all point to the same object Person (23, "zhang "). This phenomenon can be called reference replication. (For the distinction between references and objects, refer to my previous article on why strings in Java are immutable? -- String source code analysis, which describes the distinction between references and objects ). After the above code is executed, the scenario in the memory is shown in:
The following code clones an object.
Person p = new Person(23, "zhang");Person p1 = (Person) p.clone();System.out.println(p);System.out.println(p1);

The printed results show that the addresses of the two objects are different. That is to say, a new object is created, instead of assigning the original object address to a new reference variable: com. pansoft. zhangjg. testclone. person @ 2f9ee1ac
Com. pansoft. zhangjg. testclone. Person @ 67f1fba0

After the above code is executed, the scenario in the memory is shown in:



Deep copy or light copy
In the above sample code, there are two member variables in Person: name and age. name is of the String type and age is of the int type. The code is very simple, as shown below:
public class Person implements Cloneable{private int age ;private String name;public Person(int age, String name) {this.age = age;this.name = name;}public Person() {}public int getAge() {return age;}public String getName() {return name;}@Overrideprotected Object clone() throws CloneNotSupportedException {return (Person)super.clone();}}


Because age is a basic data type, there is no doubt about its copy. simply copy a 4-byte integer. However, name is of the String type, and it is only a reference pointing to a real String object. There are two ways to copy it: directly copy the reference value of name in the source object to the name field of the new object, or create a new same String object based on the string object pointed to by name in the original Person object, assign the reference of the New String object to the name field of the newly copied Person object. The two copy methods are called shortest copy and deep copy respectively. The principles of deep copy and shallow copy are as follows:

The following code is used for verification. If the address values of the two Person objects are the same, the names of both objects point to the same String object, that is, the shortest copy. If the address values of the two objects are different, it means that it points to different String objects, that is, when copying the Person object, it also copies the String object referenced by name, that is, the deep copy. The verification code is as follows:
Person p = new Person (23, "zhang"); Person p1 = (Person) p. clone (); System. out. println ("p. getName (). hashCode (): "+ p. getName (). hashCode (); System. out. println ("p1.getName (). hashCode (): "+ p1.getName (). hashCode (); String result = p. getName (). hashCode () = p1.getName (). hashCode ()? "Clone is a shortest copy": "clone is a deep copy"; System. out. println (result );

The output is p. getName (). hashCode (): 115864556.
P1.getName (). hashCode (): 115864556
Clone is a shortest copy.

Therefore, the clone method executes a shortest copy. Pay attention to this detail when writing a program.

Overwrite the clone method in the Object to implement deep copy.
To perform a deep copy when cloning an object, we need the Clonable interface to overwrite and implement the clone method. In addition to calling the clone method in the parent class to obtain a new object, the referenced variables in the class are also cloned. If only the default clone method in the Object is used, it is a shortest copy, and the following code is verified again:
static class Body implements Cloneable{public Head head;public Body() {}public Body(Head head) {this.head = head;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}}static class Head /*implements Cloneable*/{public  Face face;public Head() {}public Head(Face face){this.face = face;}} public static void main(String[] args) throws CloneNotSupportedException {Body body = new Body(new Head());Body body1 = (Body) body.clone();System.out.println("body == body1 : " + (body == body1) );System.out.println("body.head == body1.head : " +  (body.head == body1.head));}

In the above Code, there are two main classes: Body and Face. In the Body class, a Face object is combined. When cloning a Body object, the combined Face object only performs a shortest copy. Print the result to verify the conclusion: body = body1: false
Body. head = body1.head: true

If you want to make the Body object perform a deep copy during clone, You need to clone the Head object referenced by the source object in the clone method of the Body.
static class Body implements Cloneable{public Head head;public Body() {}public Body(Head head) {this.head = head;}@Overrideprotected Object clone() throws CloneNotSupportedException {Body newBody =  (Body) super.clone();newBody.head = (Head) head.clone();return newBody;}}static class Head implements Cloneable{public  Face face;public Head() {}public Head(Face face){this.face = face;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}} public static void main(String[] args) throws CloneNotSupportedException {Body body = new Body(new Head());Body body1 = (Body) body.clone();System.out.println("body == body1 : " + (body == body1) );System.out.println("body.head == body1.head : " +  (body.head == body1.head));}

The printed result is body = body1: false.
Body. head = body1.head: false

It can be seen that the head reference in the body and body1 point to different Head objects, that is, while cloning the Body object, it also copies the Head object it references and performs a deep copy.

Is it a deep copy?
From the content in the previous section, we can draw the following conclusion: If you want to copy an object in depth, this object must implement the Cloneable interface, implement the clone method, and within the clone method, clone other objects referenced by this object. This requires that the referenced object must also implement the Cloneable interface and the clone method.
According to the above conclusion, the Body class combines the Head class and the Head class combines the Face class. to copy the Body class in depth, the Head class must also be copied in the clone method of the Body class. However, when the Head class is copied, the shortest copy is executed by default, that is to say, the Face object combined in the Head will not be copied. The verification code is as follows: (only the code of the Face class is provided here, but the whole program is also very short to ensure consistency and avoid losing context information)
static class Body implements Cloneable{public Head head;public Body() {}public Body(Head head) {this.head = head;}@Overrideprotected Object clone() throws CloneNotSupportedException {Body newBody =  (Body) super.clone();newBody.head = (Head) head.clone();return newBody;}}static class Head implements Cloneable{public  Face face;public Head() {}public Head(Face face){this.face = face;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}} static class Face{}public static void main(String[] args) throws CloneNotSupportedException {Body body = new Body(new Head(new Face()));Body body1 = (Body) body.clone();System.out.println("body == body1 : " + (body == body1) );System.out.println("body.head == body1.head : " +  (body.head == body1.head));System.out.println("body.head.face == body1.head.face : " +  (body.head.face == body1.head.face));}

The printed result is body = body1: false.
Body. head = body1.head: false
Body. head. face = body1.head. face: true

Shows the memory structure:

So, is this a deep copy for the Body object? In fact, it should be considered a deep copy, because other objects referenced in the Body object (currently only Head) are copied, that is to say, the head reference in two independent Body objects has already pointed to two independent Head objects. However, for the two Head objects, they point to the same Face object, which indicates that the two Body objects are still related and not completely independent. This should be said to be an incomplete deep copy.

How to make a thorough deep copy
In the above example, how can we ensure that the two Body objects are completely independent? As long as you copy the Head object, you can also copy the Face object. This requires the Face class to also implement the Cloneable interface, implement the clone method, and copy the referenced Face object in the clone method of the Head object. The modified code is as follows:
static class Head implements Cloneable{public  Face face;public Head() {}public Head(Face face){this.face = face;}@Overrideprotected Object clone() throws CloneNotSupportedException {//return super.clone();Head newHead = (Head) super.clone();newHead.face = (Face) this.face.clone();return newHead;}} static class Face implements Cloneable{@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}}

Run the preceding example again. The result is as follows: body = body1: false.
Body. head = body1.head: false
Body. head. face = body1.head. face: false

The two bodies are completely independent. The face objects indirectly referenced by them have been copied, that is, the independent Face objects are referenced. The memory structure is as follows:
Release/vbG00ru49rbUz/release + 9sbS1xLbUz/release + 1xMO/0ru8trbUz/release/vb1_oapl + release/ttcShoyC + release/be9v + examples + dPQttTP87a8u + Gxu7 + examples/zxNqyv9fpus/examples/X6brPwctUb290aLbUz/examples/Czbyjugo8aW1nIHNyYz0 = "http://www.bkjia.com/uploadfile/Collfiles/20140120/20140120090021290.jpg" alt = ">



Conclusion
Clone may not be used frequently during normal project development. However, distinguishing between deep copy and shallow copy gives us a better understanding of the java memory structure and running mode. As for deep copy, it is almost impossible to implement it. The reason is described in the previous section. Deep copy and thorough deep copy may have a subtle impact on the program when creating an immutable object, and may decide whether the immutable object we create is truly immutable. An important application of clone is also used to create immutable objects. I will elaborate on creating immutable objects in subsequent articles.


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.