Java中要实现clone必须实现Cloneable接口,并重写clone方法。但是惊奇的发现接口中居然空无一物,clone方法是在Object中就有定义的。
像Cloneable这样的接口被称作标记接口,其意义是:以接口的形式标记对象是否拥有某种能力。这也是接口的一种作用,为某种规范而存在(个人理解,有看法可讨论)。关于标记相关,详见:http://www.cnblogs.com/xinhuaxuan/p/6349165.html
clone分 深clone和浅clone 。
Java中Object实现的克隆为浅克隆,若对象A中有其他对象P,则若A 中的对象P发生改变时,其克隆对象A`中的P也会改变,因为其使用的引用指向同一个对象。
若想实现深克隆,需重写clone方法。可以采用序列化的方式,使用对象流实现。但被克隆对象需要实现Serializable接口
package lc.clone.deep;
import java.io.Serializable;
//要实现深克隆必须实现Serializable接口
public class DeepClone implements Serializable
{
private int a;
private String b;
private int[] c;
public int getA()
{
return a;
}
public void setA(int a)
{
this.a = a;
}
public String getB()
{
return b;
}
public void setB(String b)
{
this.b = b;
}
public int[] getC()
{
return c;
}
public void setC(int[] c)
{
this.c = c;
}
}
测试类:
package lc.clone.deep;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class Test
{
public static void main(String[] args) throws CloneNotSupportedException
{
Test t = new Test();
DeepClone dc1 = new DeepClone();
// 对dc1赋值
dc1.setA(100);
dc1.setB("clone1");
dc1.setC(new int[] { 1000 });
System.out.println("克隆前: dc1.a=" + dc1.getA());
System.out.println("克隆前: dc1.b=" + dc1.getB());
System.out.println("克隆前: dc1.c[0]=" + dc1.getC()[0]);
System.out.println("-----------");
DeepClone dc2 = (DeepClone) t.deepClone(dc1);
// 对c2进行修改
dc2.setA(50);
dc2.setB("clone2");
int[] a = dc2.getC();
a[0] = 500;
dc2.setC(a);
System.out.println("克隆前: dc1.a=" + dc1.getA());
System.out.println("克隆前: dc1.b=" + dc1.getB());
System.out.println("克隆前: dc1.c[0]=" + dc1.getC()[0]);
System.out.println("-----------");
System.out.println("克隆后: dc2.a=" + dc2.getA());
System.out.println("克隆后: dc2.b=" + dc2.getB());
System.out.println("克隆后: dc2.c[0]=" + dc2.getC()[0]);
}
// 用序列化与反序列化实现深克隆
public Object deepClone(Object src)
{
Object o = null;
try
{
if (src != null)
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(src);
oos.close();
ByteArrayInputStream bais = new ByteArrayInputStream(baos
.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
o = ois.readObject();
ois.close();
}
} catch (IOException e)
{
e.printStackTrace();
} catch (ClassNotFoundException e)
{
e.printStackTrace();
}
return o;
}
}
测试结果如下:
结果:
克隆前: dc1.a=100
克隆前: dc1.b=clone1
克隆前: dc1.c[0]=1000
-----------
克隆前: dc1.a=100
克隆前: dc1.b=clone1
克隆前: dc1.c[0]=1000
-----------
克隆后: dc2.a=50
克隆后: dc2.b=clone2
克隆后: dc2.c[0]=500
克隆前: dc1.a=100
克隆前: dc1.b=clone1
克隆前: dc1.c[0]=1000
-----------
克隆前: dc1.a=100
克隆前: dc1.b=clone1
克隆前: dc1.c[0]=1000
-----------
克隆后: dc2.a=50
克隆后: dc2.b=clone2
克隆后: dc2.c[0]=500
关于可序列化内容,日后更新学习。