A. Shallow copy (shallow copy)
1. How do I implement a shallow copy?
The object class is a direct or indirect parent class for all classes, and the Clone method exists in object, as follows
protected native throws Clonenotsupportedexception;
If you want to enable an object of a class to call the Clone method, you need to implement the Cloneable interface and override the Clone method :
Public classStudentImplementscloneable{Private intSno; PrivateString name; //getter, setter omitted@Override PublicObject Clone ()throwsclonenotsupportedexception {Student s=NULL; Try{s= (Student)Super. Clone (); }Catch(Exception e) {e.printstacktrace (); } returns; }}
Now test the Clone method:
@Test public void test04 () throws clonenotsupportedexception { // Create Student object Student s1 = new Student (); S1.setsno ( 1 "Rye" // Copy an object from clone Student S2 = (Student) S1.clone (); System.out.println ( "S1:" +s1); System.out.println ( "s2:" +s2); System.out.println ( S1 = = s2? ==> "+ (S1 == S2)); }
As expected, the field values in the cloned object S2 should be the same as S1, but the object corresponding to S1 is not in the same block of memory space as the result:
S1:student{sno=1, name= ' Rye '}s2:student{sno=1, name= ' Rye 'false
View Code
At this point if you modify the S1 in the Sno 2, then will not affect the SNO in the S2?
// Modify the SnoS1.setsno (2) in the S1;
The results are as follows:
s1:student{sno=2, name= ' Rye '}s2:student{sno=1, name= ' Rye '}
View Code
At this point it seems to have completed the copy, S1 and S2 have their own different values, but if you add a teacher type of member variable for student, the result is the same as above? Let's change the code:
Public class Teacher { privateint TNO; Private String name; // getter Setter omitted ...}
Public classStudentImplementscloneable{Private intSno; PrivateString name; PrivateTeacher Teacher; //getter, setter, toString omitted ...@Override PublicObject Clone ()throwsclonenotsupportedexception {Student s=NULL; Try{s= (Student)Super. Clone (); }Catch(Exception e) {e.printstacktrace (); } returns; } }
At this point the test code is as follows:
@Test Public voidtest02 ()throwsclonenotsupportedexception {Student student1=NewStudent (); Student1.setsno (1); Student1.setname ("Rye"); Teacher Teacher=NewTeacher (); Teacher.settno (1); Teacher.setname ("Lintong"); Student1.setteacher (teacher); Student Student2=(Student) Student1.clone (); System.out.println ("Student1:" +student1); System.out.println ("Student2:" +Student2); System.out.println ("Student1 = = Student2?" ==> "+ (Student1 = =student2)); System.out.println ("Student1.teacher = = Student2.teacher?" ==> "+ (student1.getteacher () = =Student2.getteacher ())); }
The results of the operation are as follows:
Student1:student{sno=1, name= ' Rye ', teacher=teacher{tno=1, name= ' Lintong '}}student2:student{sno=1, Name= ' Rye ', teacher=teacher{tno=1, name= ' Lintong 'falsetrue
View Code
This shows that at this time through the clone generated Student2, and Student1. Both of the teacher field, pointing to the same piece of memory space;
Then there may be people asking, what will this affect?
The purpose of our copying, more often, is to want to get new and value the same object, manipulate the original object or copy of the new object, to each other;
At this point we modify the TNO of teacher in Student1 as follows:
// Modify the TNO value in teacher to 2student1.getteacher (). Settno (2);
Run test again:
Student1:student{sno=1, name= ' Rye ', teacher=teacher{tno=2, name= ' Lintong '}}student2:student{sno=1, Name= ' Rye ', teacher=teacher{tno=2, name= ' Lintong 'falsetrue
View Code
At this time found that student2 in the teacher of the TNO, but also changed.
The reason for this change is that when you execute clone through Student1, the base type is completely copied to the Student2 corresponding object memory space, but the teacher object is simply a copy of the teacher reference.
The reference to Student1 and Student2 refers to the same heap of memory, so either Student1 or Student2 modifies the teacher to affect the other;
The diagram will be more intuitive:
2. Shallow copy of the reference type of variable copy is an object reference, can be resolved by the following ideas:
The Clone method is also covered in the teacher class:
@Override protected Object Clone () { null; Try { = (Teacher)Super. Clone (); Catch (clonenotsupportedexception e) { e.printstacktrace (); } return teacher; }
Modify the Clone method in student as follows:
@Override public Object Clone () { null; Try { = (Student)Super. Clone (); = (Teacher)this. Teacher.clone (); S.setteacher (t); } Catch (Exception e) { e.printstacktrace (); } return s; }
Run test again at this point:
Student1:student{sno=1, name= ' Rye ', teacher=teacher{tno=2, name= ' Lintong '}}student2:student{sno=1, Name= ' Rye ', teacher=teacher{tno=1, name= ' Lintong 'false
View Code
As a conclusion, the teacher has also been modified at the same time as copy student:
For now, it's satisfying our needs, but what if there are other member variables of the reference type in the teacher class?
Then it is also necessary to always overwrite the Clone method, if this relationship is not more acceptable, if the reference relationship is complex, it will appear cumbersome code;
In this case, the deep copy should be completed using serialization;
Two. Deep copy
Using serialization to complete a deep copy
Deep copy is the use of object flow, the object is serialized, and then deserialized to derive new objects. So the first step is to implement the serialization interface, as follows:
Public class Implements serializable{ privatestaticfinallong serialversionuid =- 2232725257771333130L; Private int Sno; Private String name; Private Teacher Teacher;
Getter, setter,tostring () omitted ...}
Teacher also implements the serialization interface:
Public class Implements serializable{ privatestaticfinallong serialversionuid = 4477679176385287943L; Private int TNO; Private String name;
Getter, setter,tostring () omitted ...
}
Tool methods:
//Tool Methods PublicObject Cloneobject (Object object)throwsIOException, ClassNotFoundException {//serialization of an objectBytearrayoutputstream OutputStream =NewBytearrayoutputstream (); ObjectOutputStream ObjectOutputStream=NewObjectOutputStream (OutputStream); Objectoutputstream.writeobject (object); //Deserialize a byteBytearrayinputstream InputStream =NewBytearrayinputstream (Outputstream.tobytearray ()); ObjectInputStream ObjectInputStream=NewObjectInputStream (InputStream); Object obj=Objectinputstream.readobject (); returnobj; }
Test class:
Public voidtest05 ()throwsIOException, classnotfoundexception {Student student1=NewStudent (); Student1.setsno (1); Student1.setname ("Rye"); Teacher Teacher=NewTeacher (); Teacher.settno (1); Teacher.setname ("Lintong"); Student1.setteacher (teacher); Student Student2=(Student) cloneobject (STUDENT1); //Modify the TNO value in teacher to 2Student1.getteacher (). Settno (2); System.out.println ("Student1:" +student1); System.out.println ("Student2:" +Student2); System.out.println ("Student1 = = Student2?" ==> "+ (Student1 = =student2)); System.out.println ("Student1.teacher = = Student2.teacher?" ==> "+ (student1.getteacher () = =Student2.getteacher ())); }
If the teacher class or the student class does not implement a serialized interface, the execution will report an exception, as follows:
Java.io.NotSerializableException:com.example.test.Teacher
In the case where the serializable interface is implemented, the results are as follows:
Student1:student{sno=1, name= ' Rye ', teacher=teacher{tno=2, name= ' Lintong '}}student2:student{sno=1, Name= ' Rye ', teacher=teacher{tno=1, name= ' Lintong 'false
View Code
Through the way of object flow, the deep copy is successfully completed.
Three. Overriding the Clone method is compared to two copies of the serialization:
Clone method:
Advantages: fast speed, high efficiency
Cons: Using this method is cumbersome when object references are deep
by serialization:
Pros: Very simple to complete deep copy
Disadvantage: Because the serialization process needs to deal with the disk, the efficiency is lower than the clone mode
How to choose?
In actual development, according to the pros and cons of the two ways to choose!
Talking about the deep copy in Java