Java/Class/Clone

Материал из Java эксперт
Перейти к: навигация, поиск

A Cloning Example

     

public class MainClass {
  public static void main(String[] args) {
    Employee emp1 = new Employee("M", "A");
    emp1.setSalary(40000.0);
    Employee emp2 = (Employee) emp1.clone();
    emp1.setLastName("Smith");
    System.out.println(emp1);
    System.out.println(emp2);
  }
}
class Employee {
  private String lastName;
  private String firstName;
  private Double salary;
  public Employee(String lastName, String firstName) {
    this.lastName = lastName;
    this.firstName = firstName;
  }
  public String getLastName() {
    return this.lastName;
  }
  public void setLastName(String lastName) {
    this.lastName = lastName;
  }
  public String getFirstName() {
    return this.firstName;
  }
  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }
  public Double getSalary() {
    return this.salary;
  }
  public void setSalary(Double salary) {
    this.salary = salary;
  }
  public Object clone() {
    Employee emp;
    emp = new Employee(this.lastName, this.firstName);
    emp.setSalary(this.salary);
    return emp;
  }
  public String toString() {
    return this.getClass().getName() + "[" + this.firstName + " " + this.lastName + ", "
        + this.salary + "]";
  }
}





A collection of utilities to workaround limitations of Java clone framework

  
/*
 * $HeadURL$
 * $Revision$
 * $Date$
 *
 * 
 *
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 * 
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 */
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * A collection of utilities to workaround limitations of Java clone framework.
 */
public class CloneUtils {
    public static Object clone(final Object obj) throws CloneNotSupportedException {
        if (obj == null) {
            return null;
        }
        if (obj instanceof Cloneable) {
            Class<?> clazz = obj.getClass ();
            Method m;
            try {
                m = clazz.getMethod("clone", (Class[]) null);
            } catch (NoSuchMethodException ex) {
                throw new NoSuchMethodError(ex.getMessage());
            }
            try {
                return m.invoke(obj, (Object []) null);
            } catch (InvocationTargetException ex) {
                Throwable cause = ex.getCause();
                if (cause instanceof CloneNotSupportedException) {
                    throw ((CloneNotSupportedException) cause); 
                } else {
                    throw new Error("Unexpected exception", cause);
                }
            } catch (IllegalAccessException ex) {
                throw new IllegalAccessError(ex.getMessage());
            }
        } else {
            throw new CloneNotSupportedException();
        }
    }
    
    /**
     * This class should not be instantiated.
     */
    private CloneUtils() {
    }
}





Arrays are automatically cloneable

   
public class Main {
  public static void main(String[] argv) throws Exception {
    int[] ints = new int[] { 123, 234 };
    int[] intsClone = (int[]) ints.clone();
  }
}





Checking to see if a reference can be cloned

    
// : appendixa:CheckCloneable.java
// Checking to see if a reference can be cloned.
// From "Thinking in Java, 3rd ed." (c) Bruce Eckel 2002
// www.BruceEckel.ru. See copyright notice in CopyRight.txt.
// Can"t clone this because it doesn"t override clone():
class Ordinary {
}
// Overrides clone, but doesn"t implement Cloneable:
class WrongClone extends Ordinary {
  public Object clone() throws CloneNotSupportedException {
    return super.clone(); // Throws exception
  }
}
// Does all the right things for cloning:
class IsCloneable extends Ordinary implements Cloneable {
  public Object clone() throws CloneNotSupportedException {
    return super.clone();
  }
}
// Turn off cloning by throwing the exception:
class NoMore extends IsCloneable {
  public Object clone() throws CloneNotSupportedException {
    throw new CloneNotSupportedException();
  }
}
class TryMore extends NoMore {
  public Object clone() throws CloneNotSupportedException {
    // Calls NoMore.clone(), throws exception:
    return super.clone();
  }
}
class BackOn extends NoMore {
  private BackOn duplicate(BackOn b) {
    // Somehow make a copy of b and return that copy.
    // This is a dummy copy, just to make the point:
    return new BackOn();
  }
  public Object clone() {
    // Doesn"t call NoMore.clone():
    return duplicate(this);
  }
}
// You can"t inherit from this, so you can"t override
// the clone method as you can in BackOn:
final class ReallyNoMore extends NoMore {
}
public class CheckCloneable {
  public static Ordinary tryToClone(Ordinary ord) {
    String id = ord.getClass().getName();
    System.out.println("Attempting " + id);
    Ordinary x = null;
    if (ord instanceof Cloneable) {
      try {
        x = (Ordinary) ((IsCloneable) ord).clone();
        System.out.println("Cloned " + id);
      } catch (CloneNotSupportedException e) {
        System.err.println("Could not clone " + id);
      }
    } else {
      System.out.println("Doesn"t implement Cloneable");
    }
    return x;
  }
  public static void main(String[] args) {
    // Upcasting:
    Ordinary[] ord = { new IsCloneable(), new WrongClone(), new NoMore(),
        new TryMore(), new BackOn(), new ReallyNoMore(), };
    Ordinary x = new Ordinary();
    // This won"t compile; clone() is protected in Object:
    //! x = (Ordinary)x.clone();
    // Checks first to see if a class implements Cloneable:
    for (int i = 0; i < ord.length; i++)
      tryToClone(ord[i]);
  }
} ///:~





Class is declared to be cloneable.

   

class Employee implements Cloneable {
  String name;
  int salary;
  public Employee(String name, int salary) {
    this.name = name;
    this.salary = salary;
  }
  public Employee() {
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public void setSalary(int salary) {
    this.salary = salary;
  }
  public int getSalary() {
    return this.salary;
  }
  public Object clone() throws CloneNotSupportedException {
    try {
      return super.clone();
    } catch (CloneNotSupportedException cnse) {
      System.out.println("CloneNotSupportedException thrown " + cnse);
      throw new CloneNotSupportedException();
    }
  }
}
public class Main {
  public static void main(String[] args) {
    try {
      Employee e = new Employee("Dolly", 1000);
      System.out.println(e);
      System.out.println("The employee"s name is " + e.getName());
      System.out.println("The employees"s pay is " + e.getSalary());
      Employee eClone = (Employee) e.clone();
      System.out.println(eClone);
      System.out.println("The clone"s name is " + eClone.getName());
      System.out.println("The clones"s pay is " + eClone.getSalary());
    } catch (CloneNotSupportedException cnse) {
      System.out.println("Clone not supported");
    }
  }
}





Clone an object with clone method from parent

   
public class Main {
  public static void main(String[] args) {
    try {
      Employee e = new Employee("Dolly", 1000);
      System.out.println(e);
      System.out.println("The employee"s name is " + e.getName());
      System.out.println("The employees"s pay is " + e.getSalary());
      Employee eClone = (Employee) e.clone();
      System.out.println(eClone);
      System.out.println("The clone"s name is " + eClone.getName());
      System.out.println("The clones"s pay is " + eClone.getSalary());
      eClone.setName("Polly");
      eClone.setSalary(2000);
      System.out.println("The employee"s name is " + e.getName());
      System.out.println("The employees"s pay is " + e.getSalary());
      System.out.println("The clone"s name is " + eClone.getName());
      System.out.println("The clones"s pay is " + eClone.getSalary());
    } catch (Exception e) {
      System.out.println("Exception " + e);
    }
  }
}
class Employee implements Cloneable {
  private StringBuffer name;
  private int salary;
  public Employee(String name, int salary) {
    this.name = new StringBuffer(name);
    this.salary = salary;
  }
  public Employee() {
  }
  public Object clone() throws CloneNotSupportedException {
    try {
      return super.clone();
    } catch (CloneNotSupportedException cnse) {
      System.out.println("CloneNotSupportedException thrown " + cnse);
      throw new CloneNotSupportedException();
    }
  }
  public String getName() {
    return name.toString();
  }
  public void setName(String name) {
    this.name.delete(0, this.name.length());
    this.name.append(name);
  }
  public void setSalary(int salary) {
    this.salary = salary;
  }
  public int getSalary() {
    return this.salary;
  }
}





Clone demo

    
/*
 * Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002.
 * All rights reserved. Software written by Ian F. Darwin and others.
 * $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS""
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 * 
 * Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee
 * cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
 * pioneering role in inventing and promulgating (and standardizing) the Java 
 * language and environment is gratefully acknowledged.
 * 
 * The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
 * inventing predecessor languages C and C++ is also gratefully acknowledged.
 */
class One extends java.lang.Object {
  int x;
}
class Two extends One /*implements Cloneable*/ {
  int y;
  public void foo() {
    try {
      Object o = this.clone();
    } catch (CloneNotSupportedException ex) {
      System.err.println(ex);
    }
  }
  public Object clone() throws CloneNotSupportedException {
    return super.clone();
  }
}
public class CloneSub {
  public static void main(String[] args) throws CloneNotSupportedException {
    Two t1 = new Two();
    t1.x = 100;
    t1.y = 200;
    Two t2 = (Two)t1.clone();
    System.out.println(t2);
    System.out.println(t2.y);
  }
}





Clone objects

    
public class Main {
  public static void main(String[] args) {
    Person person1 = new Person();
    person1.setFirstName("F");
    person1.setLastName("L");
    Person person2 = (Person) person1.clone();
    Person person3 = (Person) person2.clone();
    System.out.println("Person 1: " + person1.getFirstName() + " " + person1.getLastName());
    System.out.println("Person 2: " + person2.getFirstName() + " " + person2.getLastName());
    System.out.println("Person 3: " + person3.getFirstName() + " " + person3.getLastName());
  }
}
class Person implements Cloneable {
  private String firstName;
  private String lastName;
  public Object clone() {
    Person obj = new Person();
    obj.setFirstName(this.firstName);
    obj.setLastName(this.lastName);
    return obj;
  }
  public String getFirstName() {
    return firstName;
  }
  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }
  public String getLastName() {
    return lastName;
  }
  public void setLastName(String lastName) {
    this.lastName = lastName;
  }
}
/*
Person 1: F L
Person 2: F L
Person 3: F L
*/





Clone Via Serialization

 
/** 
 * 
 * The ObjectStyle Group Software License, version 1.1
 * ObjectStyle Group - http://objectstyle.org/
 * 
 * Copyright (c) 2002-2005, Andrei (Andrus) Adamchik and individual authors
 * of the software. All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 
 * 3. The end-user documentation included with the redistribution, if any,
 *    must include the following acknowlegement:
 *    "This product includes software developed by independent contributors
 *    and hosted on ObjectStyle Group web site (http://objectstyle.org/)."
 *    Alternately, this acknowlegement may appear in the software itself,
 *    if and wherever such third-party acknowlegements normally appear.
 * 
 * 4. The names "ObjectStyle Group" and "Cayenne" must not be used to endorse
 *    or promote products derived from this software without prior written
 *    permission. For written permission, email
 *    "andrus at objectstyle dot org".
 * 
 * 5. Products derived from this software may not be called "ObjectStyle"
 *    or "Cayenne", nor may "ObjectStyle" or "Cayenne" appear in their
 *    names without prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED ``AS IS"" AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * 
 * 
 * This software consists of voluntary contributions made by many
 * individuals and hosted on ObjectStyle Group web site.  For more
 * information on the ObjectStyle Group, please see
 * <http://objectstyle.org/>.
 */
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.lang.reflect.Member;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.ruparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
/**
 * Contains various unorganized static utility methods used across Cayenne.
 * 
 * @author Andrei Adamchik
 */
public class Util {
  /**
   * Creates Serializable object copy using serialization/deserialization.
   */
  public static Object cloneViaSerialization(Serializable obj) throws Exception {
      ByteArrayOutputStream bytes = new ByteArrayOutputStream() {
          public synchronized byte[] toByteArray() {
              return buf;
          }
      };
      ObjectOutputStream out = new ObjectOutputStream(bytes);
      out.writeObject(obj);
      out.close();
      ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes
              .toByteArray()));
      Object objCopy = in.readObject();
      // no need to close the stream - we created it and now will be throwing away...
      // in.close();
      
      return objCopy;
  }
}





Cloning a composed object

    
// : appendixa:DeepCopy.java
// Cloning a composed object.
// {Depends: junit.jar}
// From "Thinking in Java, 3rd ed." (c) Bruce Eckel 2002
// www.BruceEckel.ru. See copyright notice in CopyRight.txt.
import junit.framework.*;
class DepthReading implements Cloneable {
  private double depth;
  public DepthReading(double depth) {
    this.depth = depth;
  }
  public Object clone() {
    Object o = null;
    try {
      o = super.clone();
    } catch (CloneNotSupportedException e) {
      e.printStackTrace();
    }
    return o;
  }
  public double getDepth() {
    return depth;
  }
  public void setDepth(double depth) {
    this.depth = depth;
  }
  public String toString() {
    return String.valueOf(depth);
  }
}
class TemperatureReading implements Cloneable {
  private long time;
  private double temperature;
  public TemperatureReading(double temperature) {
    time = System.currentTimeMillis();
    this.temperature = temperature;
  }
  public Object clone() {
    Object o = null;
    try {
      o = super.clone();
    } catch (CloneNotSupportedException e) {
      e.printStackTrace();
    }
    return o;
  }
  public double getTemperature() {
    return temperature;
  }
  public void setTemperature(double temperature) {
    this.temperature = temperature;
  }
  public String toString() {
    return String.valueOf(temperature);
  }
}
class OceanReading implements Cloneable {
  private DepthReading depth;
  private TemperatureReading temperature;
  public OceanReading(double tdata, double ddata) {
    temperature = new TemperatureReading(tdata);
    depth = new DepthReading(ddata);
  }
  public Object clone() {
    OceanReading o = null;
    try {
      o = (OceanReading) super.clone();
    } catch (CloneNotSupportedException e) {
      e.printStackTrace();
    }
    // Must clone references:
    o.depth = (DepthReading) o.depth.clone();
    o.temperature = (TemperatureReading) o.temperature.clone();
    return o; // Upcasts back to Object
  }
  public TemperatureReading getTemperatureReading() {
    return temperature;
  }
  public void setTemperatureReading(TemperatureReading tr) {
    temperature = tr;
  }
  public DepthReading getDepthReading() {
    return depth;
  }
  public void setDepthReading(DepthReading dr) {
    this.depth = dr;
  }
  public String toString() {
    return "temperature: " + temperature + ", depth: " + depth;
  }
}
public class DeepCopy extends TestCase {
  public DeepCopy(String name) {
    super(name);
  }
  public void testClone() {
    OceanReading reading = new OceanReading(33.9, 100.5);
    // Now clone it:
    OceanReading clone = (OceanReading) reading.clone();
    TemperatureReading tr = clone.getTemperatureReading();
    tr.setTemperature(tr.getTemperature() + 1);
    clone.setTemperatureReading(tr);
    DepthReading dr = clone.getDepthReading();
    dr.setDepth(dr.getDepth() + 1);
    clone.setDepthReading(dr);
    assertEquals(reading.toString(), "temperature: 33.9, depth: 100.5");
    assertEquals(clone.toString(), "temperature: 34.9, depth: 101.5");
  }
  public static void main(String[] args) {
    junit.textui.TestRunner.run(DeepCopy.class);
  }
} ///:~





Creating a Deep Copy

     
public class MainClass {
  public static void main(String[] args) {
    Employee emp1 = new Employee("M", "A");
    emp1.setSalary(40000.0);
    emp1.address = new Address("First Street", "San F", "CA", "93702");
    Employee emp2 = (Employee) emp1.clone();
    printEmployee(emp1);
    printEmployee(emp2);
    emp2.setLastName("Smith");
    emp2.address = new Address("Street", "B", "CA", "93722");
    printEmployee(emp1);
    printEmployee(emp2);
  }
  private static void printEmployee(Employee e) {
    System.out.println(e.getFirstName() + " " + e.getLastName());
    System.out.println(e.address.getAddress());
    System.out.println("Salary: " + e.getSalary());
  }
}
class Employee implements Cloneable {
  private String lastName;
  private String firstName;
  private Double salary;
  public Address address;
  public Employee(String lastName, String firstName) {
    this.lastName = lastName;
    this.firstName = firstName;
    this.address = new Address();
  }
  public String getLastName() {
    return this.lastName;
  }
  public void setLastName(String lastName) {
    this.lastName = lastName;
  }
  public String getFirstName() {
    return this.firstName;
  }
  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }
  public Double getSalary() {
    return this.salary;
  }
  public void setSalary(Double salary) {
    this.salary = salary;
  }
  public Object clone() {
    Employee emp;
    try {
      emp = (Employee) super.clone();
      emp.address = (Address) address.clone();
    } catch (CloneNotSupportedException e) {
      return null; // will never happen
    }
    return emp;
  }
  public String toString() {
    return this.getClass().getName() + "[" + this.firstName + " " + this.lastName + ", "
        + this.salary + "]";
  }
}
class Address implements Cloneable {
  private String street;
  private String city;
  private String state;
  private String zipCode;
  public Address() {
    this.street = "";
    this.city = "";
    this.state = "";
    this.zipCode = "";
  }
  public Address(String street, String city, String state, String zipCode) {
    this.street = street;
    this.city = city;
    this.state = state;
    this.zipCode = zipCode;
  }
  public Object clone(){
    try {
      return super.clone();
    } catch (CloneNotSupportedException e) {
      return null; // will never happen
    }
  }
  public String getAddress() {
    return this.street + "\n" + this.city + ", " + this.state + " " + this.zipCode;
  }
}





Creating local copies with clone

    
// : appendixa:LocalCopy.java
// Creating local copies with clone().
// From "Thinking in Java, 3rd ed." (c) Bruce Eckel 2002
// www.BruceEckel.ru. See copyright notice in CopyRight.txt.

class MyObject implements Cloneable {
  private int n;
  public MyObject(int n) {
    this.n = n;
  }
  public Object clone() {
    Object o = null;
    try {
      o = super.clone();
    } catch (CloneNotSupportedException e) {
      System.err.println("MyObject can"t clone");
    }
    return o;
  }
  public int getValue() {
    return n;
  }
  public void setValue(int n) {
    this.n = n;
  }
  public void increment() {
    n++;
  }
  public String toString() {
    return Integer.toString(n);
  }
}
public class LocalCopy {
  public static MyObject g(MyObject v) {
    // Passing a reference, modifies outside object:
    v.increment();
    return v;
  }
  public static MyObject f(MyObject v) {
    v = (MyObject) v.clone(); // Local copy
    v.increment();
    return v;
  }
  public static void main(String[] args) {
    MyObject a = new MyObject(11);
    MyObject b = g(a);
    // Reference equivalence, not object equivalence:
    System.out.println("a == b: " + (a == b) + "\na = " + a + "\nb = " + b);
    MyObject c = new MyObject(47);
    MyObject d = f(c);
    System.out.println("c == d: " + (c == d) + "\nc = " + c + "\nd = " + d);
  }
} ///:~





Deep clone Object

 
/*
 * Copyright (C) 2001-2003 Colin Bell
 * colbell@users.sourceforge.net
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
import java.io.*;
import java.text.NumberFormat;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
 * General purpose utilities functions.
 *
 * @author 
 */
public class Utilities
{
  
  /**
   * Creates a clone of any serializable object. Collections and arrays
   * may be cloned if the entries are serializable.
   *
   * Caution super class members are not cloned if a super class is not serializable.
   */
  public static Object cloneObject(Object toClone, final ClassLoader classLoader)
  {
     if(null == toClone)
     {
        return null;
     }
     else
     {
        try
        {
           ByteArrayOutputStream bOut = new ByteArrayOutputStream();
           ObjectOutputStream oOut = new ObjectOutputStream(bOut);
           oOut.writeObject(toClone);
           oOut.close();
           ByteArrayInputStream bIn = new ByteArrayInputStream(bOut.toByteArray());
           bOut.close();
           ObjectInputStream oIn = new ObjectInputStream(bIn)
           {
              protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException
              {
                return Class.forName(desc.getName(), false, classLoader);
              }
           };
           bIn.close();
           Object copy = oIn.readObject();
           oIn.close();
           return copy;
        }
        catch (Exception e)
        {
           throw new RuntimeException(e);
        }
     }
  }
}





Deep clone serializing/de-serializng Clone

   
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
 * Utility for object cloning
 * 
 * @author 
 */
public class CloneUtil
{
    /**
     * Provides a deep clone serializing/de-serializng <code>objToClone</code>     
     * 
     * @param objToClone The object to be cloned
     * @return The cloned object
     */
    public static final Object deepClone(Object objToClone)
    {
        try
        {
            ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream(100);
            ObjectOutputStream objectoutputstream = new ObjectOutputStream(bytearrayoutputstream);
            objectoutputstream.writeObject(objToClone);
            byte abyte0[] = bytearrayoutputstream.toByteArray();
            objectoutputstream.close();
            ByteArrayInputStream bytearrayinputstream = new ByteArrayInputStream(abyte0);
            ObjectInputStream objectinputstream = new ObjectInputStream(bytearrayinputstream);
            Object clone = objectinputstream.readObject();
            objectinputstream.close();
            return clone;
        }
        catch (Exception exception)
        {
            // nothing
        }
        return null;
    }
}





Deep Copy Test

    
/*
Correct Output:
Original (orginal values): Person-A - Civic
Clone (before change): Person-A - Civic
Clone (after change): Person-B - Accord
Original (after clone is modified): Person-A - Civic
*/
/*
Software Architecture Design Patterns in Java
by Partha Kuchana 
Auerbach Publications
*/

class Person implements Cloneable {
  //Lower-level object
  private Car car;
  private String name;
  public Car getCar() {
    return car;
  }
  public String getName() {
    return name;
  }
  public void setName(String s) {
    name = s;
  }
  public Person(String s, String t) {
    name = s;
    car = new Car(t);
  }
  public Object clone() {
    //Deep copy
    Person p = new Person(name, car.getName());
    return p;
  }
}
class Car {
  private String name;
  public String getName() {
    return name;
  }
  public void setName(String s) {
    name = s;
  }
  public Car(String s) {
    name = s;
  }
}
public class DeepCopyTest {
  public static void main(String[] args) {
    //Original Object
    Person p = new Person("Person-A", "Civic");
    System.out.println("Original (orginal values): " + p.getName() + " - "
        + p.getCar().getName());
    //Clone as a shallow copy
    Person q = (Person) p.clone();
    System.out.println("Clone (before change): " + q.getName() + " - "
        + q.getCar().getName());
    //change the primitive member
    q.setName("Person-B");
    //change the lower-level object
    q.getCar().setName("Accord");
    System.out.println("Clone (after change): " + q.getName() + " - "
        + q.getCar().getName());
    System.out.println("Original (after clone is modified): " + p.getName()
        + " - " + p.getCar().getName());
  }
}





Demonstration of cloning

    
/*
 * Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002.
 * All rights reserved. Software written by Ian F. Darwin and others.
 * $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS""
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 * 
 * Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee
 * cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
 * pioneering role in inventing and promulgating (and standardizing) the Java 
 * language and environment is gratefully acknowledged.
 * 
 * The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
 * inventing predecessor languages C and C++ is also gratefully acknowledged.
 */
/** Demonstration of cloning. */
public class Clone1 implements Cloneable {
  /** Clone this object. Call super.clone() to do the work */
  public Object clone() {
    try {
      return super.clone();
    } catch (CloneNotSupportedException ex) {
      System.out.println("Now that"s a surprise!!");
      throw new InternalError(ex.toString());
    }
  }
  int x;
  transient int y;  // will be cloned, but not serialized
  /** Display the current object as a string */
  public String toString() {
    return "Clone1[" + x + "," + y + "]";
  }
}





Go through a few gyrations to add cloning to your own class

    
// : appendixa:AddingClone.java
// You must go through a few gyrations
// to add cloning to your own class.
// From "Thinking in Java, 3rd ed." (c) Bruce Eckel 2002
// www.BruceEckel.ru. See copyright notice in CopyRight.txt.
import java.util.ArrayList;
import java.util.Iterator;
class Int2 implements Cloneable {
  private int i;
  public Int2(int ii) {
    i = ii;
  }
  public void increment() {
    i++;
  }
  public String toString() {
    return Integer.toString(i);
  }
  public Object clone() {
    Object o = null;
    try {
      o = super.clone();
    } catch (CloneNotSupportedException e) {
      System.err.println("Int2 can"t clone");
    }
    return o;
  }
}
// Inheritance doesn"t remove cloneability:
class Int3 extends Int2 {
  private int j; // Automatically duplicated
  public Int3(int i) {
    super(i);
  }
}
public class AddingClone {
  public static void main(String[] args) {
    Int2 x = new Int2(10);
    Int2 x2 = (Int2) x.clone();
    x2.increment();
    System.out.println("x = " + x + ", x2 = " + x2);
    // Anything inherited is also cloneable:
    Int3 x3 = new Int3(7);
    x3 = (Int3) x3.clone();
    ArrayList v = new ArrayList();
    for (int i = 0; i < 10; i++)
      v.add(new Int2(i));
    System.out.println("v: " + v);
    ArrayList v2 = (ArrayList) v.clone();
    // Now clone each element:
    for (int i = 0; i < v.size(); i++)
      v2.set(i, ((Int2) v2.get(i)).clone());
    // Increment all v2"s elements:
    for (Iterator e = v2.iterator(); e.hasNext();)
      ((Int2) e.next()).increment();
    System.out.println("v2: " + v2);
    // See if it changed v"s elements:
    System.out.println("v: " + v);
  }
} ///:~





Implements a pool of internalized objects

 
/*
 * Copyright 2007 (C) TJDO.
 * All rights reserved.
 *
 * This software is distributed under the terms of the TJDO License version 1.0.
 * See the terms of the TJDO License in the documentation provided with this software.
 *
 * $Id: InternPool.java,v 1.1 2007/11/30 19:42:26 jackknifebarber Exp $
 */

import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.AbstractCollection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.WeakHashMap;

/**
 * Implements a pool of <dfn>internalized</dfn> objects.
 * Used to implement pools that behave like the one used by String.intern().
 * <p>
 * This implementation is synchronized.
 * It is a generic collection that is unmodifiable with the exception of the
 * {@link #intern} method.
 *
 * @author 
 * @version $Revision: 1.1 $
 */
public class InternPool extends AbstractCollection
{
    private final Map pool = new WeakHashMap();
    /**
     * Returns a canonical representation for the specified object.
     * <p>
     * This method behaves much like <code>String.intern()</code>.
     * A pool of objects, initially empty, is maintained privately.
     * <p>
     * If the pool already contains an object equal to the specified object as
     * determined by the <code>equals(Object)</code> method, then the object
     * from the pool is returned.
     * Otherwise, the specified object is added to the pool and a reference to
     * the specified object is returned.
     * <p>
     * It follows that for any two objects <code>o1</code> and <code>o2</code>,
     * <code>intern(o1)&nbsp;==&nbsp;intern(o2)</code> is <code>true</code>
     * if and only if <code>o1.equals(o2)</code> is <code>true</code>.
     *
     * @param candidate
     *      the object to internalize
     *
     * @return
     *      an object that is equivalent to the specified object, but is
     *      guaranteed to be from a pool of unique objects.
     */
    public synchronized Object intern(Object candidate)
    {
        Reference ref = (Reference)pool.get(candidate);
        Object pooled = ref == null ? null : ref.get();
        if (pooled == null)
        {
            pooled = candidate;
            pool.put(pooled, new WeakReference(pooled));
        }
        return pooled;
    }
    public synchronized boolean contains(Object o)
    {
        return pool.containsKey(o);
    }
    public synchronized Iterator iterator()
    {
        return Collections.unmodifiableSet(pool.keySet()).iterator();
    }
    public synchronized int size()
    {
        return pool.size();
    }
}





Manipulate properties after clone operation

   
public class Main {
  public static void main(String[] args) {
    try {
      Employee e = new Employee("B", 1000);
      System.out.println(e);
      System.out.println("The employee"s name is " + e.getName());
      System.out.println("The employees"s pay is " + e.getSalary());
      Employee eClone = (Employee) e.clone();
      System.out.println(eClone);
      System.out.println("The clone"s name is " + eClone.getName());
      System.out.println("The clones"s pay is " + eClone.getSalary());
      eClone.setName("A");
      eClone.setSalary(2000);
      System.out.println("The employee"s name is " + e.getName());
      System.out.println("The employees"s pay is " + e.getSalary());
      System.out.println("The clone"s name is " + eClone.getName());
      System.out.println("The clones"s pay is " + eClone.getSalary());
    } catch (Exception e) {
      System.out.println("Exception " + e);
    }
  }
}
class Employee implements Cloneable {
  private StringBuffer name;
  private int salary;
  public Employee(String name, int salary) {
    this.name = new StringBuffer(name);
    this.salary = salary;
  }
  public Employee() {
  }
  public Object clone() throws CloneNotSupportedException {
    try {
      Employee o = (Employee) super.clone();
      o.name = new StringBuffer(name.toString());
      return o;
    } catch (CloneNotSupportedException cnse) {
      System.out.println("CloneNotSupportedException thrown " + cnse);
      throw new CloneNotSupportedException();
    }
  }
  public String getName() {
    return name.toString();
  }
  public void setName(String name) {
    this.name.delete(0, this.name.length());
    this.name.append(name);
  }
  public void setSalary(int salary) {
    this.salary = salary;
  }
  public int getSalary() {
    return this.salary;
  }
}





Serializable and clone

    
// : appendixa:Compete.java
// From "Thinking in Java, 3rd ed." (c) Bruce Eckel 2002
// www.BruceEckel.ru. See copyright notice in CopyRight.txt.
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
class Thing1 implements Serializable {
}
class Thing2 implements Serializable {
  Thing1 o1 = new Thing1();
}
class Thing3 implements Cloneable {
  public Object clone() {
    Object o = null;
    try {
      o = super.clone();
    } catch (CloneNotSupportedException e) {
      System.err.println("Thing3 can"t clone");
    }
    return o;
  }
}
class Thing4 implements Cloneable {
  private Thing3 o3 = new Thing3();
  public Object clone() {
    Thing4 o = null;
    try {
      o = (Thing4) super.clone();
    } catch (CloneNotSupportedException e) {
      System.err.println("Thing4 can"t clone");
    }
    // Clone the field, too:
    o.o3 = (Thing3) o3.clone();
    return o;
  }
}
public class Compete {
  public static final int SIZE = 25000;
  public static void main(String[] args) throws Exception {
    Thing2[] a = new Thing2[SIZE];
    for (int i = 0; i < a.length; i++)
      a[i] = new Thing2();
    Thing4[] b = new Thing4[SIZE];
    for (int i = 0; i < b.length; i++)
      b[i] = new Thing4();
    long t1 = System.currentTimeMillis();
    ByteArrayOutputStream buf = new ByteArrayOutputStream();
    ObjectOutputStream o = new ObjectOutputStream(buf);
    for (int i = 0; i < a.length; i++)
      o.writeObject(a[i]);
    // Now get copies:
    ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(
        buf.toByteArray()));
    Thing2[] c = new Thing2[SIZE];
    for (int i = 0; i < c.length; i++)
      c[i] = (Thing2) in.readObject();
    long t2 = System.currentTimeMillis();
    System.out.println("Duplication via serialization: " + (t2 - t1)
        + " Milliseconds");
    // Now try cloning:
    t1 = System.currentTimeMillis();
    Thing4[] d = new Thing4[SIZE];
    for (int i = 0; i < d.length; i++)
      d[i] = (Thing4) b[i].clone();
    t2 = System.currentTimeMillis();
    System.out.println("Duplication via cloning: " + (t2 - t1)
        + " Milliseconds");
  }
} ///:~





Serializable Clone

 
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public abstract class SerializableClone {
  public static Object clone(final Object obj) throws Exception {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    ObjectOutputStream oout = new ObjectOutputStream(out);
    oout.writeObject(obj);
    ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray()));
    return in.readObject();
  }
}





Shallow Copy Test

    
/*
Software Architecture Design Patterns in Java
by Partha Kuchana 
Auerbach Publications
*/

class Person implements Cloneable {
  //Lower-level object
  private Car car;
  private String name;
  public Car getCar() {
    return car;
  }
  public String getName() {
    return name;
  }
  public void setName(String s) {
    name = s;
  }
  public Person(String s, String t) {
    name = s;
    car = new Car(t);
  }
  public Object clone() {
    //shallow copy
    try {
      return super.clone();
    } catch (CloneNotSupportedException e) {
      return null;
    }
  }
}
class Car {
  private String name;
  public String getName() {
    return name;
  }
  public void setName(String s) {
    name = s;
  }
  public Car(String s) {
    name = s;
  }
}
public class ShallowCopyTest {
  public static void main(String[] args) {
    //Original Object
    Person p = new Person("Person-A", "Civic");
    System.out.println("Original (orginal values): " + p.getName() + " - "
        + p.getCar().getName());
    //Clone as a shallow copy
    Person q = (Person) p.clone();
    System.out.println("Clone (before change): " + q.getName() + " - "
        + q.getCar().getName());
    //change the primitive member
    q.setName("Person-B");
    //change the lower-level object
    q.getCar().setName("Accord");
    System.out.println("Clone (after change): " + q.getName() + " - "
        + q.getCar().getName());
    System.out.println("Original (after clone is modified): " + p.getName()
        + " - " + p.getCar().getName());
  }
}





Simple demo of avoiding side-effects by using Object.clone

    
/*
 * Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002.
 * All rights reserved. Software written by Ian F. Darwin and others.
 * $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS""
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 * 
 * Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee
 * cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
 * pioneering role in inventing and promulgating (and standardizing) the Java 
 * language and environment is gratefully acknowledged.
 * 
 * The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
 * inventing predecessor languages C and C++ is also gratefully acknowledged.
 */
import java.util.*;
/**
 * Simple demo of avoiding side-effects by using Object.clone()
 * to duplicate an object before passing it to your enemy"s methods.
 * Cloneable is a "marker" interface: it has no methods, but is tested
 * for by Object.clone. If you implement it, you tell Object.clone that
 * your data is stable enough that field-by-field copy is OK.
 */
class Enemy {
  public void munge(SideEffects md) {
    System.out.println("Object is " + md);
    md.year = 0;
    md.td.setYear(71);    // Ignore deprecation warnings
  }
}
public class SideEffects implements Cloneable {
  /** When we clone a "SideEffects", this REFERENCE gets cloned */
  public Date td;  
  /** When we clone a "SideEffects", this integer does NOT get cloned */
  volatile int year;
  public static void main(String[] argv) throws CloneNotSupportedException {
    new SideEffects().process();
  }
  SideEffects() {
    td = new Date();  // today
    year = td.getYear();
  }
  public void process() throws CloneNotSupportedException {
    Enemy r = new Enemy();
    System.out.println("We have seen the enemy, and he is " + r);
    System.out.println("Today is " + td + "; nice weather, isn"t it?");
    System.out.println("And the year is " + year);
    r.munge((SideEffects)this.clone());
    System.out.println("Why, I believe it is now " + td);
    if (year == 0)    // should not happen!!
      System.out.println("** PANIC IN YEAR ZERO **");
    System.out.println("But wait, the year is still " + year);
    r.munge(this);
    System.out.println("Now I"m certain that it"s " + td);
    System.out.println("Now the year is  " + year);
  }
}





Tests cloning to see if destination of references are also cloned

    
// : appendixa:Snake.java
// Tests cloning to see if destination
// of references are also cloned.
// From "Thinking in Java, 3rd ed." (c) Bruce Eckel 2002
// www.BruceEckel.ru. See copyright notice in CopyRight.txt.
public class Snake implements Cloneable {
  private Snake next;
  private char c;
  // Value of i == number of segments
  public Snake(int i, char x) {
    c = x;
    if (--i > 0)
      next = new Snake(i, (char) (x + 1));
  }
  public void increment() {
    c++;
    if (next != null)
      next.increment();
  }
  public String toString() {
    String s = ":" + c;
    if (next != null)
      s += next.toString();
    return s;
  }
  public Object clone() {
    Object o = null;
    try {
      o = super.clone();
    } catch (CloneNotSupportedException e) {
      System.err.println("Snake can"t clone");
    }
    return o;
  }
  public static void main(String[] args) {
    Snake s = new Snake(5, "a");
    System.out.println("s = " + s);
    Snake s2 = (Snake) s.clone();
    System.out.println("s2 = " + s2);
    s.increment();
    System.out.println("after s.increment, s2 = " + s2);
  }
} ///:~





The clone operation works for only a few items in the standard Java library

    
// : appendixa:Cloning.java
// The clone() operation works for only a few
// items in the standard Java library.
// From "Thinking in Java, 3rd ed." (c) Bruce Eckel 2002
// www.BruceEckel.ru. See copyright notice in CopyRight.txt.
import java.util.ArrayList;
import java.util.Iterator;
class Int {
  private int i;
  public Int(int ii) {
    i = ii;
  }
  public void increment() {
    i++;
  }
  public String toString() {
    return Integer.toString(i);
  }
}
public class Cloning {
  public static void main(String[] args) {
    ArrayList v = new ArrayList();
    for (int i = 0; i < 10; i++)
      v.add(new Int(i));
    System.out.println("v: " + v);
    ArrayList v2 = (ArrayList) v.clone();
    // Increment all v2"s elements:
    for (Iterator e = v2.iterator(); e.hasNext();)
      ((Int) e.next()).increment();
    // See if it changed v"s elements:
    System.out.println("v: " + v);
  }
} ///:~





Uses serialization to perform deep copy cloning.

   
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class Main implements Cloneable, Serializable {
  public Object clone() {
    Object clonedObj = null;
    try {
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      ObjectOutputStream oos = new ObjectOutputStream(baos);
      oos.writeObject(this);
      oos.close();
      ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
      ObjectInputStream ois = new ObjectInputStream(bais);
      clonedObj = ois.readObject();
      ois.close();
    } catch (Exception cnfe) {
      System.out.println("Class not found " + cnfe);
    }
    return clonedObj;
  }
}





Utility for object cloning

 
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
 * Utility for object cloning
 * 
 * @author 
 */
public class CloneUtil
{
    /**
     * Provides a deep clone serializing/de-serializng <code>objToClone</code>     
     * 
     * @param objToClone The object to be cloned
     * @return The cloned object
     */
    public static final Object deepClone(Object objToClone)
    {
        try
        {
            ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream(100);
            ObjectOutputStream objectoutputstream = new ObjectOutputStream(bytearrayoutputstream);
            objectoutputstream.writeObject(objToClone);
            byte abyte0[] = bytearrayoutputstream.toByteArray();
            objectoutputstream.close();
            ByteArrayInputStream bytearrayinputstream = new ByteArrayInputStream(abyte0);
            ObjectInputStream objectinputstream = new ObjectInputStream(bytearrayinputstream);
            Object clone = objectinputstream.readObject();
            objectinputstream.close();
            return clone;
        }
        catch (Exception exception)
        {
            // nothing
        }
        return null;
    }
}





You can insert Cloneability at any level of inheritance

    
// : appendixa:HorrorFlick.java
// You can insert Cloneability at any level of inheritance.
// From "Thinking in Java, 3rd ed." (c) Bruce Eckel 2002
// www.BruceEckel.ru. See copyright notice in CopyRight.txt.

class Person {
}
class Hero extends Person {
}
class Scientist extends Person implements Cloneable {
  public Object clone() {
    try {
      return super.clone();
    } catch (CloneNotSupportedException e) {
      // This should never happen: It"s Cloneable already!
      throw new RuntimeException(e);
    }
  }
}
class MadScientist extends Scientist {
}
public class HorrorFlick {
  public static void main(String[] args) {
    Person p = new Person();
    Hero h = new Hero();
    Scientist s = new Scientist();
    MadScientist m = new MadScientist();
    //! p = (Person)p.clone(); // Compile error
    //! h = (Hero)h.clone(); // Compile error
    s = (Scientist) s.clone();
    m = (MadScientist) m.clone();
  }
} ///:~