clone方法
clone是定义一个Object类下基本方法之一:
protected native Object clone() throws CloneNotSupportedException;
使用的时候需要继承object对象,并且为了可以使其它类调用该方法,覆写克隆方法时必须将其作用域设置为public.
浅拷贝
浅拷贝就拷贝了对象本身,属性值不变,也就是说对象里面的引用还是原来对象里面的引用
class A implements Cloneable {
int a = 0;
int[] b = {1, 2};
@Override
protected Object clone() throws CloneNotSupportedException {
A a = null;
try {
a = (A) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return a;
}
}
测试一下
A a = new A();
A b = (A) a.clone();
System.out.println(b.a);
for (int i :b.b) {
System.out.print(i);
}
b.a = 1;
b.b[0] = 3;
b.b[1] = 4;
System.out.println(a.a);
for (int i :a.b) {
System.out.print(i);
}
测试结果是:
0 1,2
0 3,4
因为a是基本类型所以值不变,但是b是引用类型,所以值也被改变了
深拷贝
和浅拷贝就一些细微区别,深拷贝是把对象中的属性也进行了一个拷贝
class A implements Cloneable {
int a = 0;
int[] b = {1, 2};
@Override
protected Object clone() throws CloneNotSupportedException {
A a = null;
try {
a = (A) super.clone();
// 对属性进克隆
a.b = b.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return a;
}
}
测试结果是:
0 1,2
0 1,2
循环引用
如果类中的对象引用了其他的对象,那么一次次去clone显然不现实
借助java的序列化,A需要实现序列化接口,而且A中使用的所有对象都要实现序列化接口,否则会抛出NotSerializableException异常
@Override
protected Object clone() throws CloneNotSupportedException {
A a = null;
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(this);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
a = (A) ois.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return a;
}