In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-15 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
How to analyze the clone method in Java, I believe that many inexperienced people are at a loss about it. Therefore, this paper summarizes the causes and solutions of the problem. Through this article, I hope you can solve this problem.
The creation of objects in Java
Clone, as its name implies, is copying. In the Java language, clone methods are called by objects, so objects are copied. The so-called copy object first allocates a space of the same size as the source object and creates a new object in that space. So how many ways can you create objects in the java language?
Create an object using the new operator
Use the clone method to copy an object
So what are the similarities and differences between the two ways? The new operator is meant to allocate memory. When the program executes to the new operator, it first looks at the type after the new operator, because it knows the type so that it knows how much memory space to allocate. After allocating memory, call the constructor to populate the fields of the object. This step is called object initialization. After the constructor returns, an object can be created and its reference (address) can be published externally. This reference can be used externally to manipulate the object. While clone is similar to new in step * *, it allocates memory. When the clone method is called, the memory allocated is the same as the source object (that is, the object that calls the clone method), and then the corresponding fields in the original object are used to populate the domain of the new object. After the filling is completed, the clone method returns, a new same object is created, and the reference of the new object can also be published externally.
Copy object or copy reference
Similar code like the following is very common in Java:
Person p = new Person (23, "zhang"); Person p1 = p; System.out.println (p); System.out.println (p1)
When Person p1 = p; is executed, is a new object created? First of all, look at the printed results:
Com.pansoft.zhangjg.testclone.Person@2f9ee1ac
Com.pansoft.zhangjg.testclone.Person@2f9ee1ac
But you can see that the printed address values are the same, and since the addresses are all the same, it must be the same object. P and p1 are just references, and they both point to the same object Person (23, "zhang"). This phenomenon can be called the replication of references. (for the distinction between references and objects, you can refer to my previous article why String in Java is immutable. -String source code analysis, which has a section on the distinction between references and objects. After the execution of the above code is complete, the scenario in memory is as follows:
And the following code really clones an object.
Person p = new Person (23, "zhang"); Person p1 = (Person) p.clone (); System.out.println (p); System.out.println (p1)
As you can see from the print results, the addresses of the two objects are different, that is, a new object is created instead of assigning the address of the original object 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 memory is shown in the following figure:
Deep copy or shallow copy
In the sample code above, there are two member variables in Person, name and age. Name is of type String and age is of type int. The code is very simple, as follows:
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; @ Override protected Object clone () throws CloneNotSupportedException {return (Person) super.clone ();}}
Since age is a basic data type, there is no doubt about its copy, just copy a 4-byte integer value over. But name is of type String, and it's just a reference pointing to a real String object, so there are two ways to copy it: directly copy the reference value of the 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 the name in the original Person object, and assign the reference of the new string object to the name field of the newly copied Person object. These two copy methods are called shallow copy and deep copy respectively. The principles of deep and shallow copies are shown in the following figure:
The following is verified by code. If the address value of the name of two Person objects is the same, it means that the name of both objects points to the same String object, that is, a shallow copy, while if the address value of the name of the two objects is different, it means that it points to different String objects, that is, when copying the Person object, the String object referenced by name is copied, that is, a deep copy. The verification code is as follows:
Person p = new Person (23, "zhang"); Person p1 = (Person) p.clone (); String result = p.getName () = p1.getName ()? "clone is shallow copy": "clone is deep copy"; System.out.println (result)
The print result is as follows:
Clone is a shallow copy.
Therefore, the clone method performs a shallow copy, and you should pay attention to this detail when writing the program.
Override the clone method in Object to achieve deep copy
Now in order to make a deep copy of the clone object, you need the Clonable interface to override and implement the clone method, not only calling the clone method in the parent class to get the new object, but also clone the reference variables in the class. If you just use the default clone method in Object, which is a shallow copy, verify it again with the following code:
Static class Body implements Cloneable {public Head head; public Body () {} public Body (Head head) {this.head = head;} @ Override protected 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, which combine a Face object in the Body class. When a Body object is clone, its combined Face object is only shallowly copied. Print the results to verify this conclusion:
Body = = body1: false body.head = = body1.head: true
If you want to make a deep copy of the Body object during clone, you should also clone the Head object referenced by the source object in the clone method of Body.
Static class Body implements Cloneable {public Head head; public Body () {} public Body (Head head) {this.head = head;} @ Override protected 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;} @ Override protected 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 print result is as follows:
Body = = body1: false body.head = = body1.head: false
Thus it can be seen that the head references in body and body1 point to different Head objects, that is, while the clone Body object is being copied, the Head object referenced by it is also copied deeply.
Is it really a deep copy?
From the content of the previous section, we can draw the following conclusion: if you want to deeply copy an object, the object must implement the Cloneable interface and the clone method, and inside the clone method, other objects referenced by the object must also be clone, which requires that the referenced object must also implement the Cloneable interface and the clone method.
So, according to the above conclusion, the Body class combines the Head class, and the Head class combines the Face class. If you want to make a deep copy of the Body class, you must copy the Head class in the clone method of the Body class, but when copying the Head class, the default is a shallow copy, which means that the Face objects combined in the Head will not be copied. The verification code is as follows: (originally, only the code of the Face class will be given here, but in order to be consistent in reading and avoid losing context information, the whole program is also very short.)
Static class Body implements Cloneable {public Head head; public Body () {} public Body (Head head) {this.head = head;} @ Override protected 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;} @ Override protected 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 print result is as follows:
Body = = body1: false
Body.head = = body1.head: false
Body.head.face = = body1.head.face: true
The memory structure diagram is shown in the following figure:
So, for Body objects, is this a deep copy? In fact, it should be a deep copy, because other objects referenced in the Body object (currently only Head) have been copied, which means that the head references in two separate Body objects already point to two separate Head objects. However, for two Head objects, they point to the same Face object, which means 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
For 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 that the Face class also implement the Cloneable interface, implement the clone method, and copy the Face object that it references in the clone method of the Head object. The modified part of the code is as follows:
Static class Head implements Cloneable {public Face face; public Head () {} public Head (Face face) {this.face = face;} @ Override protected 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 {@ Override protected Object clone () throws CloneNotSupportedException {return super.clone ();}}
Run the above example again, and the result is as follows:
Body = = body1: false
Body.head = = body1.head: false
Body.head.face = = body1.head.face: false
This means that the two Body are completely independent, and the face objects they indirectly refer to have been copied, that is, they refer to separate Face objects. The memory structure is as follows:
And so on, if the Face object references other objects, such as Mouth, if not processed, the copy of the Body object will still be referenced to the same Mouth object through a level-by-level reference. By the same token, if you want to make Body completely independent on the reference chain, you can only explicitly have the Mouth object copied.
At this point, we can draw the following conclusion: if you want to make the copied object and the source object completely independent of each other when copying an object, then each level of the object on the reference chain must be explicitly copied. So it is very troublesome to create a thorough deep copy, especially if the reference relationship is very complex, or if a third-party object is referenced at some level of the reference chain, and this object does not implement the clone method, then all referenced objects after it are shared. For example, if the Face class referenced by Head is a class in a third-party library and does not implement the Cloneable interface, then all objects after Face will be referenced by both Body objects before and after the copy. Suppose the Mouth object is grouped inside the Face object, and the Tooth object is combined inside the Mouth object. The memory structure is shown below:
Clone may not be used very frequently in the development of normal projects, but distinguishing between deep and shallow copies will give us a better understanding of the memory structure and operation of java. As for a thorough deep copy, it is almost impossible, and the reason has been explained in the previous section. Deep copy and thorough deep copy may have a subtle impact on the program when creating immutable objects, and may determine whether the immutable objects we create are really immutable. An important application of clone is also for the creation of immutable objects.
After reading the above, do you know how to parse the clone method in Java? If you want to learn more skills or want to know more about it, you are welcome to follow the industry information channel, thank you for reading!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.