catalogue
- 01. Object copy
- 02. Understand shallow copies
- 2.1 What is shallow Copy
- 2.2 Shallow copy Cases
- 03. Understand deep copy
- 3.1 What is a Deep Copy
- 3.2 Implementing deep Copy Cases
- 04. Serialize for copy
- 4.1 Serialization Belongs to a deep copy
- 4.2 Key Points
- 4.3 Serialization Case
- 05. Delayed copy
- 06. How do I select a copy mode
- 07. Copies of arrays
- 7.1 Array of basic data types
- 7.2 Referencing arrays of data types
- 08. Copies of collections
- 8.1 Shallow copy of collections
- 8.2 Set Deep Copy
Good news
- Summary of blog notes [March 2016 to now], including Java basic and in-depth knowledge points, Android technology blog, Python learning notes, etc., including the summary of the bugs encountered in daily development, of course, also in the work of a large number of interview questions collected, long-term update maintenance and correction, continuous improvement… Open source files are in Markdown format! At the same time, also open source life blog, accumulated from 12 years, a total of N [nearly 1 million words, moved to the Internet one after another], reprint please indicate the source, thank you!
- Link address:Github.com/yangchong21…
- If you feel good, you can star, thank you! Of course, you are also welcome to put forward suggestions, everything starts with small, quantitative change leads to qualitative change!
01. Object copy
- Object Copy is to Copy the properties of one Object into another Object of the same class type. It is common to copy objects in a program, primarily in order to reuse some or all of the object’s data in a new context.
- There are three types of object copies in Java: Shallow Copy, Deep Copy, and Lazy Copy.
02. Understand shallow copies
2.1 What is shallow Copy
- A shallow copy is a bitwise copy of an object. It creates a new object that has an exact copy of the original object’s property values.
- If the property is of a primitive type, the value of the primitive type is copied. If the property is a memory address (reference type), the memory address is copied, so if one object changes the address, the other object will be affected.
- In the figure above, the SourceObject has an int property “field1” and a reference property “refObj” (referring to ContainedObject). When you make a shallow copy of the SourceObject, you create CopiedObject, which has a property “field2” containing the copy value of “field1” and still a reference to refObj itself. Since “field1” is a primitive type, we just copy its value to “field2”, but since “refObj” is a reference type, CopiedObject points to the same address as “refObj”. So any change to the “refObj” in the SourceObject will affect CopiedObject.
2.2 How to Implement shallow Copy
-
Let’s look at an example of implementing shallow copies
public class Subject { private String name; public Subject(String s) { name = s; } public String getName() { return name; } public void setName(String s) { name = s; }}Copy the code
Public class Student implements Cloneable {// Private Subject subj; private String name; public Student(String s, String sub) { name = s; subj = new Subject(sub); } public SubjectgetSubj() { return subj; } public String getName() { return name; } public void setName(String s) { name = s; } /** * rewriteclone() method * @return */ public Object clone() {// shallow copy try {// call the superclass directlyclone() methodreturn super.clone(); } catch (CloneNotSupportedException e) { returnnull; }}}Copy the code
private void test1(){// original object Student stud = new Student()"Yang Chong"."Xiaoxiang Sword Rain"); System.out.println("Original object:" + stud.getName() + "-"+ stud.getSubj().getName()); Student clonedStud = (Student) stud. Clone (); System.out.println("Copy object:" + clonedStud.getName() + "-"+ clonedStud.getSubj().getName()); // Whether the original object is the same as the copy object: system.out.println ()"Is the original object the same as the copy object?"+ (stud == clonedStud)); System.out.println(); // The name attribute of the original object is the same as that of the copy object."Is the name attribute of the original object the same as that of the copy object?"+ (stud.getName() == clonedStud.getName())); // Is the subj property of the original object the same as the copy object system.out.println ("Is the subj property of the original object the same as that of the copy object?" + (stud.getSubj() == clonedStud.getSubj())); stud.setName("Xiao Yang is funny."); stud.getSubj().setName("Xiaoxiang Sword Rain Warrior"); System.out.println("Updated original object:" + stud.getName() + "-" + stud.getSubj().getName()); System.out.println("Clone after updating the original object:" + clonedStud.getName() + "-" + clonedStud.getSubj().getName()); } Copy the code
-
The output is as follows:
2019-03-23 13:50:57.518 24704-24704/com.ycbjie.other I/System. Out: Ycbjie. other I/System. Out: Copy object: Other I/System. Out: Whether the original object and the copy object are the same:falseOther I/System. Out: Whether the name attribute of the original object is the same as that of the copy object:trueOther I/System. Out: Whether the subj properties of the original object and the copy object are the same:true2019-03-23 13:50:57.519 24704-24704/com.ycbjie.other I/ system. out: update the original object: Ycbjie. other I/ system. out: Clone object after updating the original object: Yang Chong - Xiaoxiang Sword Rain WarriorCopy the code
-
The conclusion that can be drawn
- In this example, make the class to be copied, Student, implement the Clonable interface and override the Clone () method of the Object class, then call the super.Clone () method inside the method. From the output we can see that the change made to the “name” property of the original object stud did not affect the copy object clonedStud, but the change made to the “name” property of the reference object subj did.
03. Understand deep copy
3.1 What is a Deep Copy
- A deep copy copies all properties and the dynamically allocated memory to which the properties point. A deep copy occurs when an object is copied with the object it references. Deep copies are slower and more expensive than shallow copies.
- In the figure above, the SourceObject has an int property called “field1” and a reference property called “refObj1” (referring to ContainedObject). When you make a deep copy of the SourceObject, you create CopiedObject, which has a property “field2” that contains the copy value of “field1” and a reference type property “refObj2” that contains the copy value of “refObj1”. So any changes you make to the “refObj” in the SourceObject will not affect CopiedObject
3.2 Implementing deep Copy Cases
- Here is an example of implementing deep copy. Only a small change has been made to the shallow copy example, and neither the Subject nor CopyTest classes have changed.
Public class Student implements Cloneable {// Private Subject subj; private String name; public Student(String s, String sub) { name = s; subj = new Subject(sub); } public SubjectgetSubj() { return subj; } public String getName() { return name; } public void setName(String s) { name = s; } /** * rewriteclone() method * * @return */ public Object cloneStudent s = new Student(name, subj.getname ()); Student s = new Student(name, subj.getname ());returns; }}Copy the code
- The output is as follows:
2019-03-23 13:53:48.096 25123-25123/com.ycbjie.other I/ system. out: Ycbjie. other I/ system. out: Copy object: Other I/ system. out: Whether the original object and the copy object are the same:falseOther I/ system. out: Whether the name attribute of the original object is the same as that of the copy object:true/com.ycbjie.other I/ system. out: Whether the subj properties of the original object and the copy object are the same:false2019-03-23 13:53:48.096 25123-25123/com.ycbjie.other I/ system. out: update the original object: Other I/ system. out: The clone object after the original object is updated: Yang Chong - Xiaoxiang JianyuCopy the code
- Conclusions reached
- It’s easy to spot a change in the Clone () method. Since it is a deep copy, you need to create an object of the copy class. Because there are object references in the Student class, you need to implement the Cloneable interface in the Student class and override the Clone method.
04. Serialize for copy
4.1 Serialization Belongs to a deep copy
- You might ask, what kind of copy is serialization? The answer is: deep copy through serialization. Think about this: Why do you use a deep copy of serialized objects instead of a shallow copy?
4.2 Key Points
- What can serialization do? It writes the entire object graph to a persistent storage file and reads it back when needed, which means that when you need to read it back you need a copy of the entire object graph. This is what you really need when you deep copy an object. Note that when you do a deep copy by serialization, you must ensure that all classes in the object graph are serializable.
4.3 Serialization Case
-
Take a look at the following example. It is simple to implement the Serializable interface. Android can also implement Parcelable interface.
public class ColoredCircle implements Serializable { private int x; private int y; public ColoredCircle(int x, int y) { this.x = x; this.y = y; } public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } @Override public String toString() { return "x=" + x + ", y="+ y; }}Copy the code
private void test3() { ObjectOutputStream oos = null; ObjectInputStream ois = null; Try {// create the original serializable object DouBi c1 = new DouBi(100, 100); System.out.println("The original object ="+ c1); DouBi c2 = null; Bos = new ByteArrayOutputStream(); bos = new ByteArrayOutputStream(); oos = new ObjectOutputStream(bos); // Serialize and pass the object oos. WriteObject (c1); oos.flush(); ByteArrayInputStream bin = new ByteArrayInputStream(bos.toByteArray()); ois = new ObjectInputStream(bin); // return the new object c2 = (DouBi) ois.readObject(); System.out.println();"Copied object ="+ c2); C1.setx (200); // Change the contents of the original object c1.setx (200); c1.setY(200); System.out.println();"View the original object =" + c1); System.out.println("View copied objects =" + c2); } catch (IOException e) { System.out.println("Exception in main = " + e); } catch (ClassNotFoundException e) { e.printStackTrace(); } finally { if (oos != null) { try { oos.close(); } catch (IOException e) { e.printStackTrace(); } } if(ois ! = null) { try { ois.close(); } catch (IOException e) { e.printStackTrace(); }}}}Copy the code
-
The output is as follows:
The 2019-03-23 13:53:48. 096, 25123-25123 / com. Ycbjie. The other I/System. Out: Other object = x=100, y=100 2019-03-23 13:53:48.096 25123-25123/com.ycbjie.other I/ system.out: = x=100, y=100 2019-03-23 13:53:48.096 25123-25123/com.ycbjie.other I/ system.out: Check the original object = x=200, y=200 2019-03-23 13:53:48.096 25123-25123/com.ycbjie.other I/ system. out: Check the copied object = x=100, y=100Copy the code
-
Note: Here are a few things to do:
- Ensure that all classes in the object graph are serializable
- Create input and output streams
- Use this input/output stream to create object input and object output streams
- Pass the object you want to copy to the object output stream
- Reads the new object from the object input stream and converts it back to the class of the object you sent
-
Conclusions reached
- In this example, we create a DouBi object C1 and serialize it (write it to a ByteArrayOutputStream). Then I deserialize the serialized object and save it to C2. I then modified the original object c1. And then as you can see, C1 is different from C2, and any changes you make to C1 don’t affect C2.
- Note that serialization has its own limitations and problems: Since the Transient cannot be serialized, you cannot copy the TRANSIENT using this method. Then there is performance. Creating a socket, serializing an object, transferring it through the socket, and then deserializing it is slow compared to calling methods on an existing object. So it makes a huge difference in performance. If performance is critical to your code, this is not recommended. It took almost 100 times longer than making a deep copy by implementing the Clonable interface.
05. Delayed copy
- Delayed copy is a combination of shallow and deep copies and is rarely used. This is almost unheard of before, later read a book to know that there is such a copy!
- When an object is first copied, a faster shallow copy is used, and a counter is used to record how many objects share the data. When the program wants to modify the original object, it decides whether the data is to be shared (by checking counters) and makes a deep copy as needed.
- A delayed copy looks like a deep copy from the outside, but it takes advantage of the speed of a shallow copy whenever possible. Delayed copy is used when references in the original object do not change frequently. Due to the presence of counters, the efficiency drop is high, but it is only constant level overhead. Also, in some cases, circular references can cause problems.
06. How do I select a copy mode
- A shallow copy can be used if the object’s properties are all of the basic type.
- If the object has reference properties, the shallow or deep copy is chosen based on the specific requirements.
- This means that if the object reference is not changed at any time, then there is no need to use a deep copy, only a shallow copy. If object references change frequently, then use a deep copy. There are no set rules; it all depends on specific needs.
07. Copies of arrays
- In addition to implementing the clone() method by default, Arrays also provide the arrays.copyof method for copying, both of which are shallow copies.
7.1 Array of basic data types
- As shown below.
public void test4() { int[] lNumbers1 = new int[5]; int[] rNumbers1 = Arrays.copyOf(lNumbers1, lNumbers1.length); rNumbers1[0] = 1; boolean first = lNumbers1[0] == rNumbers1[0]; Log.d("Xiao Yang is funny."."lNumbers2[0]=" + lNumbers1[0] + ",rNumbers2[0]=" + rNumbers1[0]+"-"+first); int[] lNumbers3 = new int[5]; int[] rNumbers3 = lNumbers3.clone(); rNumbers3[0] = 1; boolean second = lNumbers3[0] == rNumbers3[0]; Log.d("Xiao Yang is funny."."lNumbers3[0]=" + lNumbers3[0] + ",rNumbers3[0]=" + rNumbers3[0]+"-"+second); } Copy the code
- The output is as follows
The 2019-03-25 14:28:09. 907, 30316-30316 / org. Yczbj. Ycrefreshview D/xiao Yang to make than: LNumbers2 [0] = 0, rNumbers2 [0] = 1 - false 14:28:09. 2019-03-25, 907, 30316-30316 / org. Yczbj. Ycrefreshview D/xiao Yang to make than: lNumbers3[0]=0,rNumbers3[0]=1---falseCopy the code
7.2 Referencing arrays of data types
- As shown below.
public static void test5() { People[] lNumbers1 = new People[5]; lNumbers1[0] = new People(); People[] rNumbers1 = lNumbers1; boolean first = lNumbers1[0].equals(rNumbers1[0]); Log.d("Xiao Yang is funny."."lNumbers1[0]=" + lNumbers1[0] + ",rNumbers1[0]=" + rNumbers1[0]+"--"+first); People[] lNumbers2 = new People[5]; lNumbers2[0] = new People(); People[] rNumbers2 = Arrays.copyOf(lNumbers2, lNumbers2.length); boolean second = lNumbers2[0].equals(rNumbers2[0]); Log.d("Xiao Yang is funny."."lNumbers2[0]=" + lNumbers2[0] + ",rNumbers2[0]=" + rNumbers2[0]+"--"+second); People[] lNumbers3 = new People[5]; lNumbers3[0] = new People(); People[] rNumbers3 = lNumbers3.clone(); boolean third = lNumbers3[0].equals(rNumbers3[0]); Log.d("Xiao Yang is funny."."lNumbers3[0]=" + lNumbers3[0] + ",rNumbers3[0]=" + rNumbers3[0]+"--"+third); } public static class People implements Cloneable { int age; Holder holder; @Override protected Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } returnnull; } public static class Holder { int holderValue; }}Copy the code
- The log is as follows
The 2019-03-25 14:53:17. 054, 31093-31093 / org. Yczbj. Ycrefreshview D/xiao Yang to make than: lNumbers1 [0] = org. Yczbj. Ycrefreshview. MainActivity$People@46a2c18,rNumbers1[0]=org.yczbj.ycrefreshview.MainActivity$People@ 46 a2c18 -- true 14:53:17 2019-03-25. 054, 31093-31093 / org. Yczbj. Ycrefreshview D/xiao Yang to make than: lNumbers2[0]=org.yczbj.ycrefreshview.MainActivity$People@d344671,rNumbers2[0]=org.yczbj.ycrefreshview.MainActivity$People@ d344671 -- true 14:53:17 2019-03-25. 054, 31093-31093 / org. Yczbj. Ycrefreshview D/xiao Yang to make than: lNumbers3[0]=org.yczbj.ycrefreshview.MainActivity$People@91e9c56,rNumbers3[0]=org.yczbj.ycrefreshview.MainActivity$People@91e9c56--true Copy the code
08. Copies of collections
- Set copy is also often encountered, in general, we are using shallow copy to achieve, that is, through the constructor or clone method.
8.1 Shallow copy of collections
- Both the constructor and Clone () are shallow copies by default
public static void test6() { ArrayList<People> lPeoples = new ArrayList<>(); People people1 = new People(); lPeoples.add(people1); Log.d("Xiao Yang is funny."."lPeoples[0]=" + lPeoples.get(0)); ArrayList<People> rPeoples = (ArrayList<People>) lPeoples.clone(); Log.d("Xiao Yang is funny."."rPeoples[0]=" + rPeoples.get(0)); boolean b = lPeoples.get(0).equals(rPeoples.get(0)); Log.d("Xiao Yang is funny."."Compare two objects." + b); } public static class People implements Cloneable { int age; Holder holder; @Override protected Object clone() { try { People people = (People) super.clone(); people.holder = (People.Holder) this.holder.clone(); return people; } catch (CloneNotSupportedException e) { e.printStackTrace(); } return null; } public static class Holder implements Cloneable { int holderValue; @Override protected Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } returnnull; }}}Copy the code
- Print log
The 2019-03-25 14:56:56. 931, 31454-31454 / org. Yczbj. Ycrefreshview D/xiao Yang to make than: lPeoples [0] = org. Yczbj. Ycrefreshview. MainActivity$People46 a2c18 @ 2019-03-25 14:56:56. 931, 31454-31454 / org. Yczbj. Ycrefreshview D/xiao Yang to make than: rPeoples[0]=org.yczbj.ycrefreshview.MainActivity$People46 a2c18 @ 2019-03-25 14:56:56. 931, 31454-31454 / org. Yczbj. Ycrefreshview D/xiao Yang to make than: compare two objectstrue Copy the code
8.2 Set Deep Copy
- In some special cases, if you want to implement a deep copy of a collection, you create a new collection and add the elements to the new collection by deep copying each element of the original collection.
public static void test7() { ArrayList<People> lPeoples = new ArrayList<>(); People people1 = new People(); people1.holder = new People.Holder(); lPeoples.add(people1); Log.d("Xiao Yang is funny."."lPeoples[0]=" + lPeoples.get(0)); ArrayList<People> rPeoples = new ArrayList<>(); for (People people : lPeoples) { rPeoples.add((People) people.clone()); } Log.d("Xiao Yang is funny."."rPeoples[0]=" + rPeoples.get(0)); boolean b = lPeoples.get(0).equals(rPeoples.get(0)); Log.d("Xiao Yang is funny."."Compare two objects." + b); } public static class People implements Cloneable { int age; Holder holder; @Override protected Object clone() { try { People people = (People) super.clone(); people.holder = (People.Holder) this.holder.clone(); return people; } catch (CloneNotSupportedException e) { e.printStackTrace(); } return null; } public static class Holder implements Cloneable { int holderValue; @Override protected Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } returnnull; }}}Copy the code
- Print log
The 2019-03-25 15:00:54. 610, 31670-31670 / org. Yczbj. Ycrefreshview D/xiao Yang to make than: lPeoples [0] = org. Yczbj. Ycrefreshview. MainActivity$People46 a2c18 @ 2019-03-25 15:00:54. 610, 31670-31670 / org. Yczbj. Ycrefreshview D/xiao Yang to make than: rPeoples[0]=org.yczbj.ycrefreshview.MainActivity$People@ d344671 15:00:54. 2019-03-25, 610, 31670-31670 / org. Yczbj. Ycrefreshview D/xiao Yang to make than: compare two objectsfalse Copy the code
The other is introduced
01. About the blog summary link
- 1. Tech blogs
- 2. Open source project summary
- 3. Lifestyle blogs
- 4. Himalaya audio summary
- 5. Other summaries
02. About my blog
- My personal site: www.yczbj.org, www.ycbjie.cn
- Github:github.com/yangchong21…
- Zhihu: www.zhihu.com/people/yczb…
- Jane: www.jianshu.com/u/b7b2c6ed9…
- csdn:my.csdn.net/m0_37700275
- The Himalayan listening: www.ximalaya.com/zhubo/71989…
- Source: China my.oschina.net/zbj1618/blo…
- Soak in the days of online: www.jcodecraeer.com/member/cont.
- Email address: [email protected]
- Blog: ali cloud yq.aliyun.com/users/artic… 239.headeruserinfo.3.dT4bcV
- Segmentfault headline: segmentfault.com/u/xiangjian…
- The Denver nuggets: juejin. Cn/user / 197877…