Java Tutorial/Class Definition/Clone
Содержание
- 1 A collection of utilities to workaround limitations of Java clone framework
- 2 Arrays are automatically cloneable
- 3 Cast after cloning
- 4 Clone an array
- 5 Clone an object with clone method from parent
- 6 Construct clone of an object
- 7 construct clone of an object and call constructor in the super class
- 8 Copy an serializable object deeply
- 9 Copying Objects implements Cloneable
- 10 Deep clone Object
- 11 Deep clone serializing/de-serializng Clone
- 12 Demonstrate the clone() method.
- 13 Manipulate properties after clone operation
- 14 Override the clone() method.
- 15 public Object clone() throws CloneNotSupportedException
- 16 Serializable Clone
- 17 Shallow copy then deep copy
- 18 Uses serialization to perform deep copy cloning.
A collection of utilities to workaround limitations of Java clone framework
<source lang="java">
/*
* $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() { }
}</source>
Arrays are automatically cloneable
<source lang="java">
public class Main {
public static void main(String[] argv) throws Exception { int[] ints = new int[] { 123, 234 }; int[] intsClone = (int[]) ints.clone(); }
}</source>
Cast after cloning
<source lang="java">
class A {
int l = 1;
} class B extends A implements Cloneable {
int m = 2;
} class CloneDemo3 extends B {
int n = 3; A a = new A(); public static void main(String[] args) throws CloneNotSupportedException { CloneDemo3 c = new CloneDemo3(); CloneDemo3 c2 = (CloneDemo3) c.clone(); System.out.println(c.l); System.out.println(c2.l); System.out.println(c.m); System.out.println(c2.m); System.out.println(c.n); System.out.println(c2.n); System.out.println(c.a == c2.a); }
}</source>
Clone an array
<source lang="java">
/*
* 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. * * */
/**
* @author Stephen Colebourne * @author Moritz Petersen * @author * @author Maarten Coene * @since 2.0 * @version $Id: ArrayUtils.java 632503 2008-03-01 00:21:52Z ggregory $ */
public class Main {
// Clone //----------------------------------------------------------------------- /** * Shallow clones an array returning a typecast result and handling *null
. * * The objects in the array are not cloned, thus there is no special * handling for multi-dimensional arrays. * * This method returnsnull
for anull
input array. * * @param array the array to shallow clone, may benull
* @return the cloned array,null
ifnull
input */ public static Object[] clone(Object[] array) { if (array == null) { return null; } return (Object[]) array.clone(); } /** * Clones an array returning a typecast result and handling *null
. * * This method returnsnull
for anull
input array. * * @param array the array to clone, may benull
* @return the cloned array,null
ifnull
input */ public static long[] clone(long[] array) { if (array == null) { return null; } return (long[]) array.clone(); } /** * Clones an array returning a typecast result and handling *null
. * * This method returnsnull
for anull
input array. * * @param array the array to clone, may benull
* @return the cloned array,null
ifnull
input */ public static int[] clone(int[] array) { if (array == null) { return null; } return (int[]) array.clone(); } /** * Clones an array returning a typecast result and handling *null
. * * This method returnsnull
for anull
input array. * * @param array the array to clone, may benull
* @return the cloned array,null
ifnull
input */ public static short[] clone(short[] array) { if (array == null) { return null; } return (short[]) array.clone(); } /** * Clones an array returning a typecast result and handling *null
. * * This method returnsnull
for anull
input array. * * @param array the array to clone, may benull
* @return the cloned array,null
ifnull
input */ public static char[] clone(char[] array) { if (array == null) { return null; } return (char[]) array.clone(); } /** * Clones an array returning a typecast result and handling *null
. * * This method returnsnull
for anull
input array. * * @param array the array to clone, may benull
* @return the cloned array,null
ifnull
input */ public static byte[] clone(byte[] array) { if (array == null) { return null; } return (byte[]) array.clone(); } /** * Clones an array returning a typecast result and handling *null
. * * This method returnsnull
for anull
input array. * * @param array the array to clone, may benull
* @return the cloned array,null
ifnull
input */ public static double[] clone(double[] array) { if (array == null) { return null; } return (double[]) array.clone(); } /** * Clones an array returning a typecast result and handling *null
. * * This method returnsnull
for anull
input array. * * @param array the array to clone, may benull
* @return the cloned array,null
ifnull
input */ public static float[] clone(float[] array) { if (array == null) { return null; } return (float[]) array.clone(); } /** * Clones an array returning a typecast result and handling *null
. * * This method returnsnull
for anull
input array. * * @param array the array to clone, may benull
* @return the cloned array,null
ifnull
input */ public static boolean[] clone(boolean[] array) { if (array == null) { return null; } return (boolean[]) array.clone(); }
}</source>
Clone an object with clone method from parent
<source lang="java">
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; }
}</source>
Construct clone of an object
<source lang="java">
class Box {
double width; double height; double depth; Box(Box ob) { width = ob.width; height = ob.height; depth = ob.depth; } Box(double w, double h, double d) { width = w; height = h; depth = d; } Box() { width = -1; height = -1; depth = -1; } Box(double len) { width = height = depth = len; } double volume() { return width * height * depth; }
} class BoxWeight extends Box {
double weight; BoxWeight(double w, double h, double d, double m) { width = w; height = h; depth = d; weight = m; }
} class DemoBoxWeight {
public static void main(String args[]) { BoxWeight mybox1 = new BoxWeight(10, 20, 15, 34.3); BoxWeight mybox2 = new BoxWeight(2, 3, 4, 0.076); double vol; vol = mybox1.volume(); System.out.println(vol); System.out.println(mybox1.weight); System.out.println(); vol = mybox2.volume(); System.out.println(vol); System.out.println(mybox2.weight); }
}</source>
construct clone of an object and call constructor in the super class
<source lang="java">
class Box {
private double width; private double height; private double depth; Box(Box ob) { width = ob.width; height = ob.height; depth = ob.depth; } Box(double w, double h, double d) { width = w; height = h; depth = d; } Box() { width = -1; height = -1; depth = -1; } Box(double len) { width = height = depth = len; } double volume() { return width * height * depth; }
} class BoxWeight extends Box {
double weight; BoxWeight(BoxWeight ob) { super(ob); weight = ob.weight; } BoxWeight(double w, double h, double d, double m) { super(w, h, d); weight = m; } BoxWeight() { super(); weight = -1; } BoxWeight(double len, double m) { super(len); weight = m; }
} class DemoSuper {
public static void main(String args[]) { BoxWeight mybox1 = new BoxWeight(10, 20, 15, 34.3); BoxWeight mybox2 = new BoxWeight(2, 3, 4, 0.076); BoxWeight mybox3 = new BoxWeight(); BoxWeight mycube = new BoxWeight(3, 2); BoxWeight myclone = new BoxWeight(mybox1); double vol; vol = mybox1.volume(); System.out.println("Volume of mybox1 is " + vol); System.out.println("Weight of mybox1 is " + mybox1.weight); System.out.println(); vol = mybox2.volume(); System.out.println("Volume of mybox2 is " + vol); System.out.println("Weight of mybox2 is " + mybox2.weight); System.out.println(); vol = mybox3.volume(); System.out.println("Volume of mybox3 is " + vol); System.out.println("Weight of mybox3 is " + mybox3.weight); System.out.println(); vol = myclone.volume(); System.out.println("Volume of myclone is " + vol); System.out.println("Weight of myclone is " + myclone.weight); System.out.println(); vol = mycube.volume(); System.out.println("Volume of mycube is " + vol); System.out.println("Weight of mycube is " + mycube.weight); System.out.println(); }
}</source>
Copy an serializable object deeply
<source lang="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; /*
* JBoss, Home of Professional Open Source * Copyright 2005, JBoss Inc., and individual contributors as indicated * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This 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 software 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 software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */
public class Main {
// /////////////////////////////////////////////////////////////////////// // Cloning Methods // // /////////////////////////////////////////////////////////////////////// /** * Copy an serializable object deeply. * * @param obj * Object to copy. * @return Copied object. * * @throws IOException * @throws ClassNotFoundException */ public static Object copy(final Serializable obj) throws IOException, ClassNotFoundException { ObjectOutputStream out = null; ObjectInputStream in = null; Object copy = null; try { // write the object ByteArrayOutputStream baos = new ByteArrayOutputStream(); out = new ObjectOutputStream(baos); out.writeObject(obj); out.flush(); // read in the copy byte data[] = baos.toByteArray(); ByteArrayInputStream bais = new ByteArrayInputStream(data); in = new ObjectInputStream(bais); copy = in.readObject(); } finally { out.close(); in.close(); } return copy; }
}</source>
Copying Objects implements Cloneable
<source lang="java">
class Flea implements Cloneable {
public Flea() { } public void setName(String aName) { name = aName; } public String getName() { return name; } public String getSpecies() { return species; } public void sound() { System.out.println("Psst"); } public String toString() { return super.toString() + "\nIt"s " + name + " the " + species; } public Object clone() throws CloneNotSupportedException { return super.clone(); } private String name; private String species;
} public class MainClass {
public static void main(String[] args) { try { Flea myPet = new Flea(); myPet.setName("my name"); Flea yourPet = (Flea) myPet.clone(); yourPet.setName("Gnasher"); System.out.println("\nYour pet details:\n" + yourPet); System.out.println("\nMy pet details:\n" + myPet); } catch (CloneNotSupportedException e) { e.printStackTrace(System.err); } }
}</source>
Your pet details: Flea@360be0 It"s Gnasher the null My pet details: Flea@45a877 It"s my name the null
Deep clone Object
<source lang="java">
/*
* 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); } } }
}</source>
Deep clone serializing/de-serializng Clone
<source lang="java">
/*
* 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 objToClone
*
* @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;
}
}</source>
Demonstrate the clone() method.
<source lang="java">
class TestClone implements Cloneable {
int a; double b; TestClone cloneTest() { try { return (TestClone) super.clone(); } catch (CloneNotSupportedException e) { System.out.println("Cloning not allowed."); return this; } }
} class CloneDemo {
public static void main(String args[]) { TestClone x1 = new TestClone(); TestClone x2; x1.a = 10; x1.b = 20.98; x2 = x1.cloneTest(); // clone x1 System.out.println("x1: " + x1.a + " " + x1.b); System.out.println("x2: " + x2.a + " " + x2.b); }
}</source>
Manipulate properties after clone operation
<source lang="java">
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; }
}</source>
Override the clone() method.
<source lang="java">
class TestClone implements Cloneable {
int a; double b; public Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { System.out.println("Cloning not allowed."); return this; } }
} class CloneDemo2 {
public static void main(String args[]) { TestClone x1 = new TestClone(); TestClone x2; x1.a = 10; x1.b = 20.98; x2 = (TestClone) x1.clone(); System.out.println("x1: " + x1.a + " " + x1.b); System.out.println("x2: " + x2.a + " " + x2.b); }
}</source>
public Object clone() throws CloneNotSupportedException
<source lang="java">
public class Main {
public static void main(String[] args) throws CloneNotSupportedException { CloneDemo2 cd2 = new CloneDemo2(); System.out.println(cd2.salary); AnotherClass ac = new AnotherClass(); System.out.println(ac.gradeLetter); AnotherClass y = (AnotherClass) ac.clone(); System.out.println(y.gradeLetter); }
} class CloneDemo2 implements Cloneable {
double salary = 50000.0;
} class AnotherClass implements Cloneable {
char gradeLetter = "C"; public Object clone() throws CloneNotSupportedException { return super.clone(); }
}</source>
Serializable Clone
<source lang="java">
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(); }
}</source>
Shallow copy then deep copy
<source lang="java">
class A {
int l = 1;
} class B extends A implements Cloneable {
int m = 2;
} class CloneDemo4 extends B {
int n = 3; A a = new A(); public static void main(String[] args) throws CloneNotSupportedException { CloneDemo4 c = new CloneDemo4(); CloneDemo4 c2 = (CloneDemo4) c.clone(); System.out.println(c.l); System.out.println(c2.l); System.out.println(c.m); System.out.println(c2.m); System.out.println(c.n); System.out.println(c2.n); System.out.println(c.a == c2.a); } protected Object clone() throws CloneNotSupportedException { // First, perform a shallow copy. CloneDemo4 temp = (CloneDemo4) super.clone(); if (a != null) temp.a = new A(); return temp; }
}</source>
Uses serialization to perform deep copy cloning.
<source lang="java">
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; }
}</source>