) Java object cloning (Clone), Cloneable interface, Serializable interface in-depth discussion, phpclone object cloning

Source: Internet
Author: User

(Conversion) Java object cloning (Clone), Cloneable interface, Serializable interface in-depth discussion, phpclone object cloning

Address: http://blog.csdn.net/kenthong/article/details/5758884

Part I

Let's just start Part II.

 

Part II

When talking about object cloning, we have to explain why we need to clone the object. All objects in Java are stored in the heap, And the heap is shared globally. That is to say, if different methods of the same Java program can be referenced by an object, the quoter can modify the internal data of the object at Will (provided that the internal data of the object is exposed through the get/set method ). Sometimes, the code we write allows the caller to obtain only one copy of the object (that is, an object with identical content, but there are two such objects in the memory ), is there any way to do this? Of course, it is clone.

 

Part III

First of all, we are programmers, and of course we use the languages 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() {
// Omitting the implementation of equals (which can be automatically generated by eclipse)
}
@Override
public boolean equals(Object obj) {
// Omitting the implementation of equals (which can be automatically generated by eclipse)
}
// Omit a lot of get/set Methods
}

The code above constructs a User class and implements the java. lang. Cloneable interface. As the name suggests, Cloneable indicates that this class can be cloned.

Let's take a look at the java. lang. Cloneable interface.

/*
 * @(#)Cloneable.java1.17 05/11/17
 *
 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package java.lang;
/**
 * A class implements the Cloneable interface to 
 * indicate to the {@link java.lang.Object#clone()} method that it 
 * is legal for that method to make a 
 * field-for-field copy of instances of that class. 
 *

 

 * Invoking Object's clone method on an instance that does not implement the 
 * Cloneable interface results in the exception 
 * CloneNotSupportedException being thrown.
 *

 

 * By convention, classes that implement this interface should override 
 * Object.clone (which is protected) with a public method.
 * See {@link java.lang.Object#clone()} for details on overriding this
 * method.
 *

 

 * Note that this interface does not contain the clone method.
 * Therefore, it is not possible to clone an 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 will succeed.
 *
 * @author  unascribed
 * @version 1.17, 11/17/05
 * @see     java.lang.CloneNotSupportedException
 * @see     java.lang.Object#clone()
 * @since   JDK1.0
 */
public interface Cloneable { 
}

Don't be surprised. That's right. Except for a lot of chicken sausage, this interface does not define any method signature. That is to say, we need to clone an object, but he does not provide me with a method. What should we do? Not afraid. We still have an all-around Object class. Don't forget that he is the ancestor of all classes (god-like). So we should greet him when there is nothing to do.

/*
 * @(#)Object.java1.73 06/03/30
 *
 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package java.lang;
/**
 * Class Object is the root of the class hierarchy. 
 * Every class has Object as a superclass. All objects, 
 * including arrays, implement the methods of this class. 
 *
 * @author  unascribed
 * @version 1.73, 03/30/06
 * @see     java.lang.Class
 * @since   JDK1.0
 */
public class Object {
    
// Omitting N-plus code
    /**
     * Creates and returns a copy of this object.  The precise meaning 
     * of "copy" may depend on the class of the object. The general 
     * intent is that, for any object x, the expression:
     *
*
     * x.clone() != x
     * will be true, and that the expression:
     *
*
     * x.clone().getClass() == x.getClass()
     * will be true, but these are not absolute requirements. 
     * While it is typically the case that:
     *
*
     * x.clone().equals(x)
     * will be true, this is not an absolute requirement. 
     *

 

     * By convention, the returned object should be obtained by calling
     * super.clone.  If a class and all of its superclasses (except
     * Object) obey this convention, it will be the case that
     * x.clone().getClass() == x.getClass().
     *

 

     * By convention, the object returned by this method should be independent
     * of this object (which is being cloned).  To achieve this independence,
     * it may be necessary to modify one or more fields of the object returned
     * by super.clone before returning it.  Typically, this means
     * copying any mutable objects that 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 is usually
     * the case that no fields in the object returned by super.clone
     * need to be modified.
     *

 

     * The method clone for class Object performs a 
     * specific cloning operation. First, if the class of this object does 
     * not implement the interface Cloneable, then a 
     * CloneNotSupportedException is thrown. Note that all arrays 
     * are considered to implement the interface Cloneable. 
     * Otherwise, this method creates a new instance of the class of this 
     * object and initializes all its fields with exactly the contents of 
     * the corresponding fields of this object, as if by assignment; the
     * contents of the fields are not themselves cloned. Thus, this method 
     * performs a "shallow copy" of this object, not a "deep copy" operation.
     *

 

     * The class Object does not itself implement the interface 
     * Cloneable, so calling the clone method on an object 
     * whose class is Object will 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 Cloneable interface. Subclasses
     *               that override the clone method can also
     *               throw this exception to indicate that an instance cannot
     *               be cloned.
     * @see java.lang.Cloneable
     */
    protected native Object clone() throws CloneNotSupportedException;
}

Well, it's a huge string of chicken sausage. Don't think I'm here to get together the words. These are all technical articles written by Sun's Java developers. Let's take a look at them and talk about them.

Yes, it's a native method. It's really a profound thing, but we still have to take advantage of it. In addition, this method is protected, which clearly calls us to take advantage of it.

Continue to check the following test code.

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
}
 
}

The clone () method is awesome. We cloned our object and the execution results were as expected. The addresses of u1 and u3 are different but the content is the same.

 

Part IV

Through the above example, we can see that there are two steps to clone an object:

1. Implement the java. lang. Cloneable interface for this class;

2. override (override) the clone () method of the Object class.

But is it actually so simple? Let's 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
}

An Administrator class is defined above. This class holds an object of the User class. Next, let's take a look at the effect of cloning the 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
}
}

Heheh! Something went wrong. Java can be easily controlled!

Here we can introduce two specialized terms: shallow clone and deep clone ).

The so-called shallow cloning, as its name implies, is a very superficial clone. If we want to clone the Administrator object, we only clone its own and all its contained objects.Reference address.

Deep cloning is not a light cloning. Clone all objects except itself, including all objects contained by itselfObject instance. As for the level of deep cloning, it is determined by the specific needs. There is also "N-layer cloning.

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

If we want the object to be deeply cloned, we can modify the Administrator class in this way.

@Override
protected Object clone() throws CloneNotSupportedException {
Administrator admin = (Administrator) super.clone();
admin.user = (User) admin.user.clone();
return admin;
}

Because Boolean will cache the value, we do not need to clone the Boolean object. And the Boolean class does not implement the java. lang. Cloneable interface.

 

Part V

1. Implement the java. lang. Cloneable interface for this class;

2. Check whether the Held Object implements the java. lang. Cloneable interface and provides the clone () method;

3. override (override) the clone () method of the Object class, and call the clone () method that holds the Object within the method;

4 .......

5. it's so troublesome. If there are more than N objects, we need to write more than N methods, suddenly change the class structure, and re-Modify clone () method.

Is there no better way?

 

Part VI

Next, we will introduce how to use java. lang. Serializable to achieve deep object cloning.

First, we compile 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 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;
}
}

It doesn't matter. Just use it directly. Hey.

Next, we will test whether this tool can be used for deep cloning.

This cute TestCase, so every time you have to touch 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 complicated your object is, as long as these objects can implement java. lang. the Serializable interface can be cloned, And the cloning mechanism is completed by JVM, so it is much easier to modify the code of the entity class.

 

Why can we clone objects in this simple way? Why is the java. lang. Serializable interface used? If you want to know the answer to these questions, please remit to 0123 4567 8901 2345678.

......

Joke ...... The answer to these questions is left in the java. lang. Serializable topic. Please refer to my log. PS. It may come out in a few days. Let's see what day it's boring to write ...... Sleep enough and then ......

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.