前段时间碰到需要将一个Java对象进行深度拷贝的情况,但是JDK并未提供关于deep copy相关的API,唯一能用的就是一个不太稳定的clone(),所以问题就来了,如何实现稳定的deep copy,下面就实现deep copy的方法做个介绍。
1. 直接赋值
实现deep copy,首先想到的是可以直接赋值么?如下:
Test test = new Test();
Test test2 = test;
System.out.println(test);
System.out.println(test2);
上面的代码里,直接将test复制给test2,但是将两个对象打印出来发现,地址其实是一样的,test只是刚刚在堆上分配的Test对象的引用,而这里的赋值直接是引用直接的赋值,等于test2也是指向刚刚new出来的对象,这里的copy就是一个shallow copy,及只是copy了一份引用,但是对象实体并未copy,既然赋值不行,那就试试第二个方法,Object类的clone方法。
2. clone方法
1. clone方法介绍
Java中所有对象都继承自Object类,所以就默认自带clone方法的实现,clone方法的实现是比较简单粗暴的。首先,如果一个对象想要调用clone方法,必须实现Cloneable接口,否则会抛出CloneNotSupportedException。其实这个Cloneable是个空接口,只是个flag用来标记这个类是可以clone的,所以说将一个类声明为Cloneable与这个类具备clone能力其实并不是直接相关的。其实Cloneable是想表明具有复制这种功能,所以按理说clone应该作为Cloneable的一个方法而存在,但是实际上clone方法是Object类的一个protected方法,所以你无法直接通过多态的方式调用clone方法,比如:
public class Test implements Cloneable {
public static void main(String[] args) {
try {
List<Cloneable> list = new ArrayList<Cloneable>();
Cloneable t1 = new InnerTest("test");
list.add(t1);
list.add(t1.clone()); // 事实上,我无法这么做
} catch (Exception e) {
e.printStackTrace();
}
}
public static class InnerTest implements Cloneable {
public String a;
public InnerTest(String test) {
a = test;
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
}