An in-depth discussion of Java object Cloning (clone) and cloneable interface and serializable interface

Source: Internet
Author: User

An in-depth discussion of Java object Cloning (clone) and cloneable interface and serializable interface

Part I

There's nothing to say, just start Part II.

Part II

When it comes to cloning an object, you have to say why you want to clone the object. All objects in Java are saved in the heap, and the heap is shared globally. That is, if a different method of the same Java program, as long as you can get a reference to an object, the referrer can arbitrarily modify the object's internal data (provided that the object's internal data exposed through the Get/set method). Sometimes, the code we write wants the caller to get only one copy of the object (that is, an object with exactly the same content, but there are two such objects in memory), what is the way to do it? Cloning, of course.

Part III

First of all, we are programmers, of course, in the language of our programmers to communicate.

Import Java.util.Date;
public class User implements cloneable {
Private String username;
private String password;
Private Date birthdate;
Public User (string Username, string password, Date birthdate) {
This.username = Username;
This.password = password;
This.birthdate = birthdate;
}
@Override
Protected Object Clone () throws Clonenotsupportedexception {
return Super.clone ();
}
@Override
public int hashcode () {
Omit the implementation of equals (automatically generated with Eclipse)
}
@Override
public boolean equals (Object obj) {
Omit the implementation of equals (automatically generated with Eclipse)
}
Omit a whole bunch of get/set methods
}

The code above constructs a user class and implements the Java.lang.Cloneable interface. As the name implies, cloneable means that the class can be cloned.

And let's go and see what the Java.lang.Cloneable interface is.

/*
* @ (#) cloneable.java1.17 05/11/17
*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* SUN proprietary/confidential. Use are subject to license terms.
*/
Package Java.lang;
/**
* <p>
* <code>CloneNotSupportedException</code> being thrown.
* <p>
* <tt>Object.clone</tt> (which is protected) and a public method.
* See {@link java.lang.object#clone ()} for details on overriding this
* method.
* <p>
* Note that this interface does <i>not</i> contain the <tt>clone</tt> method.
* Therefore, it is not possible to clone a object merely by virtue of the
* fact that it implements this interface.  Even if the Clone method is invoked
* reflectively, there is no guarantee that it'll succeed.
*
* @author  unascribed
* @version 1.17, 11/17/05
* @see     Java.lang.CloneNotSupportedException
* @see     Java.lang.object#clone ()
* @since   JDK1.0
*/
}

Don't be surprised, yes, except for a whole bunch of chicken sausages, this interface doesn't define any method signatures. In other words, we're going to clone an object, but he doesn't give me a way. What should we do then? Not afraid, we also have the Almighty object class, do not forget that he is the ancestor of all classes (the existence of God), so, there is nothing to say hello to his ladyship.

/*
* @ (#) object.java1.73 06/03/30
*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* SUN proprietary/confidential. Use are subject to license terms.
*/
Package Java.lang;
/**
*
* @author  unascribed
* @version 1.73, 03/30/06
* @see     Java.lang.Class
* @since   JDK1.0
*/
public class Object {
    
   Omit N-More code
    /**
     * Creates and returns a copy of this object.  
     
     * Intent is this, for any object <tt>x</tt>, the expression:
     * <blockquote>
     * <pre>
     * X.clone ()! = x</pre></blockquote>
     * Would be true, and that the expression:
     * <blockquote>
     * <pre>
     * X.clone (). GetClass () = = X.getclass () </pre></blockquote>
     
     * While it's typically the case:
     * <blockquote>
     * <pre>
     * X.clone (). Equals (x) </pre></blockquote>
     
     * <p>
     * By convention, the returned object should is obtained by calling
     * <TT>SUPER.CLONE</TT>.  If a class and all of its superclasses (except
     * <tt>Object</tt>) Obey this convention, it'll be is the case that
     * <tt>x.clone (). GetClass () = = X.getclass () </tt>.
     * <p>
     * By convention, the object returned by this method should be independent
     * of this object (which is being cloned).  To achieve this independence,
     * It may is necessary to modify one or more fields of the object returned
     * by <tt>super.clone</tt> before returning it.  Typically, this means
     * Copying any mutable objects it comprise the internal "deep structure"
     * of the object being cloned and replacing the references to these
     * Objects with references to the copies.  If A class contains only
     * Primitive fields or references to immutable objects, then it's usually
     * The case, no fields in the object returned by <tt>super.clone</tt>
     * Need to be modified.
     * <p>
     
     
     
     
     
     
     
     * The corresponding fields of this object, as if by assignment; The
     
     * Performs a "shallow copy" of this object, not a "deep copy" operation.
     * <p>
     
     
     * Whose class is <tt>Object</tt> would result in throwing an
     * Exception at run time.
     *
     * @return     A clone of this instance.
     * @exception  clonenotsupportedexception  If the object ' s class does not
     * Support the               <code>Cloneable</code> interface. Subclasses
     * That               override the <code>clone</code> method can also
     *               Throw this exception to indicate a instance cannot
     * Be               cloned.
     * @see java.lang.Cloneable
     */
    Protected native Object clone () throws Clonenotsupportedexception;
}

Hehe, but also a large string of chicken intestines, do not think I was to make up the words, these are the sun company Java Developers write technical articles, more to see less talk it.

Yes, it is a native method, it is a very advanced thing, but we still have to take advantage of his cheap. And he this method is protected, clear is to let us to take advantage of.

Go ahead and look at the test code below.

Import Java.util.Date;
Import Org.junit.Test;
public class TestCase {
@Test
public void Testuserclone () throws Clonenotsupportedexception {
User U1 = New User ("Kent", "123456", New Date ());
User U2 = U1;
User U3 = (user) u1.clone ();
System.out.println (u1 = = U2);//True
System.out.println (U1.equals (U2));//True
System.out.println (u1 = = U3);//False
System.out.println (U1.equals (U3));//True
}
}

This clone () method is really cow, suddenly put our object cloned a copy, execution results also meet our expectations, U1 and U3 the address is different but the content is the same.

Part IV

From the above example, we can see that in order for an object to be cloned, it is actually a two-step process:

1. Let the class implement the Java.lang.Cloneable interface;

2. Override (override) the Clone () method of the object class.

But is it actually so simple? Then look at the following code.

public class Administrator implements cloneable {
private user user;
Private Boolean editable;
Public Administrator (user user, Boolean editable) {
This.user = user;
this.editable = editable;
}
@Override
Protected Object Clone () throws Clonenotsupportedexception {
return Super.clone ();
}
@Override
public int hashcode () {
Old rules
}
@Override
public boolean equals (Object obj) {
Old rules
}
Old rules
}

The above defines a administrator class that holds an object of the user class. Next, let's see what happens when cloning a administrator object.

Import Java.util.Date;
Import Org.junit.Test;
public class TestCase {
@Test
public void Testadministratorclone () throws Clonenotsupportedexception {
Administrator A1 = new Administrator (New User ("Kent", "123456", New Date ()), true);
Administrator A2 = A1;
Administrator a3 = (Administrator) a1.clone ();
SYSTEM.OUT.PRINTLN (a1 = = a2);//True
System.out.println (A1.equals (A2));//True
SYSTEM.OUT.PRINTLN (a1 = = a3);//False
System.out.println (A1.equals (A3));//True
System.out.println (a1.getuser () = = A3.getuser ());//true! It ' s not our expected!!!!!
System.out.println (A1.getuser (). Equals (A3.getuser ()));//true
}
}

Oh Ah! It's a problem. Java is so easy to control, say!

Here we can introduce two professional terms: Shallow clone (Shallow clone) and deep clone (deeper clone).

The so-called shallow clones, as the name implies is very superficial surface of the clone, if we want to clone administrator object, only the clone himself and all of the objects he contains the reference address .

And deep cloning, is non-shallow cloning. Clones all objects except themselves, including all object instances that themselves contain. As for the level of deep cloning, determined by the specific needs, there are also "N-layer cloning" one said.

However, all basic (primitive) type data, whether it is a shallow clone or a deep clone, will be cloned from the original value. After all, they are not objects, not stored in the heap. Note: The basic data types do not include their corresponding wrapper classes.

If we want the object to be deeply cloned, we can modify the administrator class like this.

@Override
Protected Object Clone () throws Clonenotsupportedexception {
Administrator admin = (Administrator) super.clone ();
Admin.user = (user) admin.user.clone ();
return admin;
}

Because Boolean caches the value, we do not need to clone the Boolean object. Also, the Boolean class does not implement the Java.lang.Cloneable interface.

Part V

1. Let the class implement the Java.lang.Cloneable interface;

2. Confirm whether the object being held implements the Java.lang.Cloneable interface and provides the clone () method;

3. Override (Override) the Clone () method of the object class and invoke the Clone () method that holds the object inside the method;

4 .....

5. Much trouble ah, tune to the tune, if there are more than n held objects, it is necessary to write n many methods, suddenly changed the structure of the class, but also to re-modify the Clone () method.

Isn't there a better way?

Part VI

The next step is to focus on using java.lang.Serializable to achieve deep cloning of objects.

First, we write a tool class and provide the Cloneto () method.

Import Java.io.ByteArrayInputStream;
Import Java.io.ByteArrayOutputStream;
Import java.io.IOException;
Import Java.io.ObjectInputStream;
Import Java.io.ObjectOutputStream;
Public abstract class Beanutil {
@SuppressWarnings ("Unchecked")
public static <T> t Cloneto (t src) throws RuntimeException {
Bytearrayoutputstream Memorybuffer = new Bytearrayoutputstream ();
ObjectOutputStream out = null;
ObjectInputStream in = null;
T dist = null;
try {
out = new ObjectOutputStream (memorybuffer);
Out.writeobject (SRC);
Out.flush ();
in = new ObjectInputStream (New Bytearrayinputstream (Memorybuffer.tobytearray ()));
Dist = (T) in.readobject ();
} catch (Exception e) {
throw new RuntimeException (e);
} finally {
if (out! = null)
try {
Out.close ();
out = null;
} catch (IOException e) {
throw new RuntimeException (e);
}
if (in = null)
try {
In.close ();
in = null;
} catch (IOException e) {
throw new RuntimeException (e);
}
}
return dist;
}
}

Don't understand, it's okay, just take it with you. Hee Hee

Next, let's test if we can use this tool to achieve deep cloning.

Again this lovely testcase, poor every time to move him ...

Import Java.util.Date;
Import Org.junit.Test;
public class TestCase {
@Test
public void Testcloneto () {
Administrator src = new Administrator (New User ("Kent", "123456", New Date ()), true);
Administrator dist = Beanutil.cloneto (src);
SYSTEM.OUT.PRINTLN (src = = dist);//False
System.out.println (Src.equals (Dist));//True
System.out.println (src.getuser () = = Dist.getuser ());//false! Well done!
System.out.println (Src.getuser (). Equals (Dist.getuser ()));//true
}
}

Well, no matter how complex your objects are, as long as these objects are able to implement the Java.lang.Serializable interface, you can clone, and this cloning mechanism is done by the JVM, no need to modify the entity class code, more convenient.

Why is it so easy to clone an object? What's the Java.lang.Serializable interface for? If you want to know the answers to these questions,

An in-depth discussion of Java object Cloning (clone) and cloneable interface and serializable interface

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.