Java deep cloning and shallow cloning.

Source: Internet
Author: User
Tags serialization shallow copy
As you know, objects are references to each other, which may contain references to another object, such as an order object, a LineItems object in the Order object, and then a LineItems object that contains the item object.


Well, now that I have an Order object Order1, it contains a LineItems object items, which means there is an orders order1, and the contents of the order are items.


OK, now there's another customer who wants an order that's exactly the same as order1, so what do we do in the logic layer of the system? Very simple, order2=order1.clone (). We know that the Clone method is to generate a new object in memory, not just the original object's reference. At this time, someone said: "Oh, understand that we modify the ORDER2 member variable, will not affect the order1." "Unfortunately, this sentence is only half right."


Assuming that the order class has a member variable name, of course changing order2.name does not affect order1.name because they are in different memory regions. But if you change order1.items. It is regrettable that the simple use of order1.clone will affect the order2.items. The simple reason is that because the Clone method defaults to shallow cloning, it does not clone objects referenced by the object, but simply copies the reference. So in the above example, the items object has only one in memory, Order1 and order2 all point to it, and any modification to it affects the other object.


The relatively shallow cloning, deep cloning nature is to clone object reference object. In other words, in the example above, changing order1.items does not affect Order2.items. Because there are two identical items in memory.


If deep cloning is implemented.

One way to do this is to rewrite the Clone method to add a statement such as order.items= (LineItems) Items.clone (), which is to artificially add a copy of the referenced object. The disadvantage of this method is that if there are many references to the object, or the reference to a lot of references, it's too much trouble. A common approach in the industry is to implement deep cloning using serialization and then drag the row. Since the object is written to the stream after serialization, all the referenced objects are included, so the drag is equal to a fully cloned object after the row is changed. Never


The requirement for this method is that the object (including the referenced object) must have the serializable interface in advance, otherwise the transient keyword is used to exclude it from the copy process.

Cloning is copying a copy of an object. But one object may have basic data types, such as Int,long,float, and also contain non basic data types such as arrays, sets, etc.
The value of the base type of the object being cloned has been modified, and the value of the original object will not change. This is suitable for shadow Clone (Shallow clone).

But if you want to change a value of a non basic type, the value of the original object changes,. For example an array, in memory only copy his address, and this address point to the value does not copy, when clone, two addresses to a value, so once the value changed, the original value of course also changed, Because they share a value. This has to be done with deep cloning (deep clone)

The following example illustrates the above: the cloned class: Shadowclone.java

public class Shallowclone implements cloneable {public
    int A;
    Public int[] B;
    
    Public Shallowclone () {
        a = 5;
        b = New int[] {1, 2, 3, 4, 5};
    }
    
    Shallow cloning, for a cloned object, only guarantees that modifications to the underlying type members do not affect the corresponding members
    //pairs of class types and members of the original object, but only the address of the object, so that modifying these type members//modifications to the cloned object
    will affect the original object
    @ Override Public
    Object Clone () {
        Shallowclone sc = null;
        try {
            sc = (shallowclone) super.clone ();
        } catch (Clonenotsupportedexception e) {
            e.printstacktrace (); c16/>} return
        SC;
    }


Test class:

public class Shallowclonetest {public
    static void Main (string[] args) throws Exception {
        //shallow clone
        Sha Llowclone sc = new Shallowclone ();
        Shallowclone sccopy = (shallowclone) sc.clone ();
        
        
        System.out.println ("Shallow Copy");
        System.out.println ("--before clone");
        System.out.println ("sc.a=" + sc.a);
        System.out.println ("sc.b=" + sc.b[0]);
        
        SCCOPY.A = 1;
        Sccopy.b[0] = ten;
        System.out.println ("--after clone");
        System.out.println ("sc.a=" + sc.a);
        System.out.println ("sc.b=" + sc.b[0]);
        System.out.println ("sccopy.a=" + sccopy.a);
        System.out.println ("sccopy.b=" + sccopy.b[0]);
    }


The results are as follows: Shallow Copy
--Before clone
SC.A = 5
SC.B = 1
--After clone
SC.A = 5
SC.B = 10
SCCOPY.A = 1
sccopy.b = 10

The problem arises, modifying the value of the cloned object Sccopy.b[0], but the value of sc.b[0] is also changed, equal to the value of sccopy.b[0].
The following is a conclusion to shallow cloning: the base type can be cloned, but the reference type is only a copy address, and there is no copy of the value of the object that this address points to, which causes two addresses to point to the same value, one of which is changed, and of course the other changes.
Thus, a shallow clone is only suitable for cloning a basic type and cannot be cloned for reference types.

So how do you implement a cloned reference object, which provides a way to do this? Implementation of deep cloning using serialization and deserialization (deep copy)

The object being cloned. Deepclone.java

Import Java.io.ByteArrayInputStream;
Import Java.io.ByteArrayOutputStream;
Import java.io.IOException;
Import Java.io.ObjectInputStream;
Import Java.io.ObjectOutputStream;

Import java.io.Serializable;
    public class Deepclone implements Serializable {private static final long serialversionuid = 1L;
    public int A;
    
    Public int[] B;
        Public Deepclone () {a = 10;
    b = New int[] {6, 7, 8, 9, 10}; ()///use ObjectInput (output) stream and bytearrayinput (output) stream for deep cloning public Object deepclone () throws Ioexcepti
        On, classnotfoundexception {deepclone dc = null;
        Bytearrayoutputstream BAOs = new Bytearrayoutputstream ();
        ObjectOutputStream oos = new ObjectOutputStream (BAOs);
        Oos.writeobject (this);
        
        Oos.close ();
        Bytearrayinputstream Bais = new Bytearrayinputstream (Baos.tobytearray ());
        ObjectInputStream bis = new ObjectInputStream (Bais);
        DC = (Deepclone) bis.readobject (); Return DC; }
}


Test class:

public class Deepclonetest {public   
	static void Main (string[] args) throws Exception {   
		Deepclone dc = new Deepclon E ();   
		Deepclone dccopy = (deepclone) dc.deepclone ();   
		System.out.println ("--before clone");   
		System.out.println ("dc.a=" + dc.a);   
		System.out.println ("dc.b=" + dc.b[0]);   
		DCCOPY.A = 1;   
		Dccopy.b[0] = 1;   

		System.out.println ("--after clone");   
		System.out.println ("dc.a=" + dc.a);   
		System.out.println ("dc.b=" + dc.b[0]);   
		System.out.println ("dccopy.a=" + dccopy.a);   
		System.out.println ("dccopy.b=" + dccopy.b[0]);   
	}   
  


The results are as follows:

--Before clone
DC.A = 10
DC.B = 6
Shallow Copy
--After clone
DC.A = 10
DC.B = 6
DCCOPY.A = 1
dccopy.b = 1

The

WriteObject method writes out the object network of the cloned class so that deep cloning can be achieved. Of course, each member type that is cloned must implement the Serializable interface

Related Article

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.