对于8种基本类型和String类型来说,克隆一般为以下:
int a = 10;
int b = a;
而对于引用类型,就相对复杂一些
定义一个测试类CloneDemo:
public class CloneDemo {
int id;
String name;
public CloneDemo(int id, String name){
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "CloneDemo [id=" + id + ", name=" + name + "]";
}
}
测试:
CloneDemo demo = new CloneDemo(1, "clone1");
CloneDemo demo1 = demo;
demo1.name = "clone2";
System.out.println(demo.toString());
System.out.println(demo1.toString());
结果:
CloneDemo [id=1, name=clone2]
CloneDemo [id=1, name=clone2]
可以看出实例demo和demo1, 引用相同的地址。所以对于引用类型克隆,不能使用一般的“=”。其在内存中表示为:
对于引用类型的克隆有浅克隆和深克隆。
浅克隆:当对象克隆时,只复制对象本身和其中包含的值类型的成员变量,而引用类型的成员对象并没有复制。
具体实现:
- 被复制的类需要实现Clonenable接口并重写clone()方法
public class CloneDemo implements Cloneable{
int id;
String name;
public CloneDemo(int id, String name){
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "CloneDemo [id=" + id + ", name=" + name + "]";
}
@Override
public Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return super.clone();
}
}
测试:
CloneDemo demo = new CloneDemo(1, "clone1");
CloneDemo demo1 = (CloneDemo) demo.clone();
demo1.name = "clone2";
System.out.println(demo.toString());
System.out.println(demo1.toString());
结果:
CloneDemo [id=1, name=clone1]
CloneDemo [id=1, name=clone2]
但是当对象中含有引用类型的成员变量时,当进行克隆时只是将引用类型成员的地址进行拷贝。
public class CloneInfo implements Cloneable{
private String infor;
// 省略 get和set, 构造函数
@Override
protected Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return super.clone();
}
}
public class CloneDemo implements Cloneable{
int id;
String name;
// 引用类型成员
CloneInfo info;
// 省略 get和set, 构造函数
@Override
protected Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return super.clone();
}
@Override
public String toString() {
return "CloneDemo [id=" + id + ", name=" + name + ", info=" + info.getInfor() + "]";
}
}
public static void main(String[] args) throws Exception {
CloneDemo demo = new CloneDemo(1,"clone1",new CloneInfo("cloneInfo1"));
CloneDemo demo1 = (CloneDemo) demo.clone();
System.out.println(demo.toString());
System.out.println(demo1.toString());
demo1.setName("clone2");
demo1.getInfo().setInfor("cloneInfo2");
System.out.println(demo.toString());
System.out.println(demo1.toString());
}
结果:
CloneDemo [id=1, name=clone1, info=cloneInfo1]
CloneDemo [id=1, name=clone1, info=cloneInfo1]
CloneDemo [id=1, name=clone1, info=cloneInfo2]
CloneDemo [id=1, name=clone2, info=cloneInfo2]
所以此时应该使用深克隆,实现深克隆有两种方法:
1.实现Cloneable接口
2.实现Serializable接口
实现Cloneable接口
public class CloneInfo implements Cloneable{
private String infor;
public CloneInfo(String info) {
this.infor = info;
}
public String getInfor() {
return infor;
}
public void setInfor(String infor) {
this.infor = infor;
}
@Override
protected Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return super.clone(); // 主要方法
}
}
public class CloneDemo implements Cloneable{
...
@Override
protected Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
CloneDemo demo = (CloneDemo)super.clone();
demo.info = (CloneInfo)info.clone(); // 引用类型成员变量进行克隆
return demo;
}
}
结果:
CloneDemo [id=1, name=clone1, info=cloneInfo1]
CloneDemo [id=1, name=clone1, info=cloneInfo1]
CloneDemo [id=1, name=clone1, info=cloneInfo1]
CloneDemo [id=1, name=clone2, info=cloneInfo2]
实现Serializable接口
public class CloneDemo implements Serializable{
private static final long serialVersionUID = 1L;
int id;
String name;
CloneInfo info;
// 省略 get和set, 构造函数
@Override
public String toString() {
return "CloneDemo [id=" + id + ", name=" + name + ", info=" + info.getInfor() + "]";
}
}
public class CloneInfo implements Serializable{
private static final long serialVersionUID = 1L;
private String infor;
// 省略 get和set, 构造函数
}
public static void main(String[] args) throws Exception {
CloneDemo demo = new CloneDemo(1,"clone1",new CloneInfo("cloneInfo1"));
CloneDemo demo1 = CloneUtil.clone(demo);
System.out.println(demo.toString());
System.out.println(demo1.toString());
demo1.setName("clone2");
demo1.getInfo().setInfor("cloneInfo2");
System.out.println(demo.toString());
System.out.println(demo1.toString());
}
结果:
CloneDemo [id=1, name=clone1, info=cloneInfo1]
CloneDemo [id=1, name=clone1, info=cloneInfo1]
CloneDemo [id=1, name=clone1, info=cloneInfo1]
CloneDemo [id=1, name=clone2, info=cloneInfo2]