First of all, why use clone?
In the actual programming process, we often encounter this situation: there is an object A, at A certain time A already contains some valid values, at this time, we may need A new object B exactly the same as A, and any change to B will not affect the value of A, that is to say, A and B are two independent objects, but the initial value of B is from A Object. In the Java language, using simple assignment statements can not meet this need. Although there are many ways to meet this demand, the implementation of clone () method is the simplest and most efficient way.
The difference between the process of an object in new and that of an object in clone
The new operator is meant to allocate memory. When the program executes to the new operator, first look at the type after the new operator, because only when you know the type can you know how much memory space to allocate. After allocating memory, the constructor is called to fill in all fields of the object. This step is called initialization of the object. After the constructor returns, an object can be created, and its reference (address) can be published to the outside, and the reference can be used to manipulate the object.
The first step of clone is similar to new, which is to allocate memory. When calling the clone method, the allocated memory is the same as the original object (that is, the object calling the clone method). Then, use the corresponding domains in the original object to fill in the domain of the new object. After filling, clone Method, a new and identical object is created, and references to the new object can also be published outside.
Use of clone objects
The difference between copying objects and copying References:
1. Person p = new Person(23, "zhang"); 2. Person p1 = p; 3. System.out.println(p); 4. System.out.println(p1);
When Person p1 = p; is a new object created? First, look at the print results:
1.com.itheima.Person@2f9ee1ac 2.com.itheima.Person@2f9ee1ac
You can see that 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 both point to the same object Person(23, "zhang"). This phenomenon can be called reference duplication. After the above code is executed, the scenario in memory is as follows:
And the following code is a true clone of an object.
1.Person p = new Person(23, "zhang"); 2.Person p1 = (Person) p.clone(); 3.System.out.println(p); 4.System.out.println(p1);
It can be seen from the printing results that the addresses of the two objects are different, that is to say, a new object is created instead of assigning the address of the original object to a new reference variable:
1. com.itheima.Person@2f9ee1ac 2. com.itheima.Person@67f1fba0
After the above code is executed, the scenario in memory is as follows:
Deep copy and light copy
In the above example code, there are two member variables in Person, namely, name and age. Name is of String type and age is of int type. The code is very simple, as follows:
1.public class Person implements Cloneable{ 2.privatint age ; 3. private String name; 4. public Person(int age, String name) { 5. this.age = age; 6. this.name = name; 7. } 8. public Person() {} 9. public int getAge() { 10. return age; 11. } 12. public String getName() { 13. return name; 14. } 15. @Override 16. protected Object clone() throws CloneNotSupportedException { 17. return (Person)super.clone(); 18. } 19.}
Since age is a basic data type, there is no doubt about its copy. Just copy a 4-byte integer value. But name is of String type. 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 original object to the name field of the new object, or according to the name in the original Person object Create a new String object with the same String object, and assign the reference of the new String object to the name field of the new copied Person object. These two copying methods are called shallow copy and deep copy respectively. The principle of deep copy and shallow copy is shown in the following figure:
The following is verified by code. If the address values of the two Person objects are the same, it means that the names of the two objects point to the same String object, that is, shallow copy. If the address values of the two objects are different, it means that they point to different String objects, that is, when copying the Person object, they copy the String object referenced by name, That is, deep copy. The verification code is as follows:
1. Person p = new Person(23, "zhang"); 2. Person p1 = (Person) p.clone(); 3. String result = p.getName() == p1.getName() 4. ? "clone It's a shallow copy" : "clone It's a deep copy"; 5. System.out.println(result);
The printing result is:
6. clone is a shallow copy
Therefore, the clone method executes a shallow copy, which should be paid attention to when writing programs.
How to make a deep copy:
From the above content, we can draw the following conclusion: if you want to copy an object in depth, the object must implement the clonable interface and the clone method, and in the clone method, you need a copy of the other objects referenced by the object, which requires that the referenced object must also implement the clonable interface and the clone method. Then, according to the above conclusion, the following code Body class combines the Head class. To copy the Body class in depth, you must copy the Head class in the clone method of the Body class. The code is as follows:
1.static class Body implements Cloneable{ 2. public Head head; 3. public Body() {} 4. public Body(Head head) {this.head = head;} 5. @Override 6. protected Object clone() throws CloneNotSupportedException { 7. Body newBody = (Body) super.clone(); 8. newBody.head = (Head) head.clone(); 9. return newBody; 10. } 11.} 12.static class Head implements Cloneable{ 13. public Face face; 14. public Head() {} 15. @Override 16. protected Object clone() throws CloneNotSupportedException { 17. return super.clone(); 18. } } 19.public static void main(String[] args) throws CloneNotSupportedException { 20. Body body = new Body(new Head(new Face())); 21. Body body1 = (Body) body.clone(); 22. System.out.println("body == body1 : " + (body == body1) ); 23. System.out.println("body.head == body1.head : " + (body.head == body1.head)); 24.}
The printing results are as follows:
1. body == body1 : false 2. body.head == body1.head : false