Java Tutorial/Class Definition/Clone
Версия от 17:44, 31 мая 2010; (обсуждение)
Содержание
- 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
/*
* $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();
}
}
Cast after cloning
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);
}
}
Clone an array
/*
* 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
* <code>null</code>.
*
* The objects in the array are not cloned, thus there is no special
* handling for multi-dimensional arrays.
*
* This method returns <code>null</code> for a <code>null</code> input array.
*
* @param array the array to shallow clone, may be <code>null</code>
* @return the cloned array, <code>null</code> if <code>null</code> 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
* <code>null</code>.
*
* This method returns <code>null</code> for a <code>null</code> input array.
*
* @param array the array to clone, may be <code>null</code>
* @return the cloned array, <code>null</code> if <code>null</code> 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
* <code>null</code>.
*
* This method returns <code>null</code> for a <code>null</code> input array.
*
* @param array the array to clone, may be <code>null</code>
* @return the cloned array, <code>null</code> if <code>null</code> 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
* <code>null</code>.
*
* This method returns <code>null</code> for a <code>null</code> input array.
*
* @param array the array to clone, may be <code>null</code>
* @return the cloned array, <code>null</code> if <code>null</code> 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
* <code>null</code>.
*
* This method returns <code>null</code> for a <code>null</code> input array.
*
* @param array the array to clone, may be <code>null</code>
* @return the cloned array, <code>null</code> if <code>null</code> 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
* <code>null</code>.
*
* This method returns <code>null</code> for a <code>null</code> input array.
*
* @param array the array to clone, may be <code>null</code>
* @return the cloned array, <code>null</code> if <code>null</code> 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
* <code>null</code>.
*
* This method returns <code>null</code> for a <code>null</code> input array.
*
* @param array the array to clone, may be <code>null</code>
* @return the cloned array, <code>null</code> if <code>null</code> 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
* <code>null</code>.
*
* This method returns <code>null</code> for a <code>null</code> input array.
*
* @param array the array to clone, may be <code>null</code>
* @return the cloned array, <code>null</code> if <code>null</code> 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
* <code>null</code>.
*
* This method returns <code>null</code> for a <code>null</code> input array.
*
* @param array the array to clone, may be <code>null</code>
* @return the cloned array, <code>null</code> if <code>null</code> input
*/
public static boolean[] clone(boolean[] array) {
if (array == null) {
return null;
}
return (boolean[]) array.clone();
}
}
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;
}
}
Construct clone of an object
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);
}
}
construct clone of an object and call constructor in the super class
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();
}
}
Copy an serializable object deeply
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;
}
}
Copying Objects implements Cloneable
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);
}
}
}
Your pet details: Flea@360be0 It"s Gnasher the null My pet details: Flea@45a877 It"s my name the null
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;
}
}
Demonstrate the clone() method.
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);
}
}
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;
}
}
Override the clone() method.
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);
}
}
public Object clone() throws CloneNotSupportedException
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();
}
}
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 then deep copy
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;
}
}
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;
}
}