Talking about the deep copy in Java

Source: Internet
Author: User
Tags object object serialization shallow copy

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

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.