随着现代科技的发展,人类已经能够克隆(clone)牛,羊等动物。Java是面向对象,也能够实现对象的克隆(clone),在之前的学习中见到引用的赋值操作,如下例所示:
首先定义一个Student类
public class Student implements Cloneable{
private String studentName;
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
}
入口函数:
public static void main(String args[]){
Student student0 = new Student();
student0.setStudentName("xiaoming");
Student student1 = student0;
System.out.println("student0.getStudentName:"+student0.getStudentName());
System.out.println("student1.getStudentName:"+student1.getStudentName());
运行结果:打印输出:
student0.getStudentName:xiaoming
student1.getStudentName:xiaoming
在入口函数中student0 被付给了student1两引用指向了内存中的同一块空间,所以通过student0对对象的操作与通过student1对对象的操作完全一致。
有时候需要创造一个student0的副本,内容与student0完全一致,但是以后可以根据需要对student1内容修改,而不会影响到student0,这时候我们就需要用到clone.
虽然Clone方法在Object中存在的,但是如果想要调用clone必须实现Cloneable接口,否则会抛出java.lang.CloneNotSupportedException。
看一下实例
public class Student implements Cloneable{
private String studentName;
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
protected Object clone() throws CloneNotSupportedException {
Student student = (Student) super.clone();
return student;
}
}
入口函数:
public static void main(String args[]){
Student student = new Student();
student.setAge(10);
student.setStudentName("xiaobai");
try {
Student s1 = (Student) student.clone();
System.out.println("student.studentName:"+student.getStudentName());
System.out.println("student.age:"+student.getAge());
System.out.println("s1.studentName:"+s1.getStudentName());
System.out.println("s1.age:"+s1.getAge());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
打印运行输出结果:
student.studentName:xiaobai
student.age:10
s1.studentName:xiaobai
s1.age:10
我们可以看出,student 和s1的内容完全一致,而且我们可以修改s1的值,而不会影响student的值。
修改入口函数:
public static void main(String args[]){
Student student = new Student();
student.setAge(10);
student.setStudentName("xiaobai");
try {
Student s1 = (Student) student.clone();
s1.setStudentName("xiaohei");
System.out.println("student.studentName:"+student.getStudentName());
System.out.println("student.age:"+student.getAge());
System.out.println("s1.studentName:"+s1.getStudentName());
System.out.println("s1.age:"+s1.getAge());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
运行结果:
student.studentName:xiaobai
student.age:10
s1.studentName:xiaohei
s1.age:10
我们发现s1的studentName值得到了修改,但是student的studentName值没有受到影响,这就是clone的作用。使用起来很简单,只需要在需要clone的对象上实现(implements)Cloneable接口,然后再在类中加上clone方法,在方法中只需要调用super.clone()即可,如上例中的部分代码:Student student = (Student)super.clone(),需要注意clone方法在当前类没有实现Cloneable的情况下可能抛出CloneNotSupportedException,所以我们需要对该异常进行处理。以上的Student类中只有基本属性,这种拷贝被称为浅拷贝。
深拷贝
如果对象中有其他对象的引用,使用浅拷贝无法完成对象的整个克隆,因为如果使用浅拷贝,只是对象的引用得到的拷贝,而两个引用是指向了同一个对象,对其中一个修改还是会影响到另外一个对象。这时后我们需要引入深拷贝,深拷贝实现起来也比较简单,只需要对对象中的对象再次进行clone操作。看以下实例
Glasses类代码如下:
public class Glasses implements Cloneable {
private String color;
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
在Student类中包含Glasses,代码如下:
public class Student implements Cloneable{
private String studentName;
private Glasses glasses;
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
public Glasses getGlasses() {
return glasses;
}
public void setGlasses(Glasses glasses) {
this.glasses = glasses;
}
protected Object clone() throws CloneNotSupportedException {
Student student = (Student) super.clone();
student.glasses= (Glasses) glasses.clone();
return student;
}
}
如果想对Glasses进行拷贝,而不是仅仅克隆Glasses的引用,在clone方法中增加了student.glasses= (Glasses) glasses.clone();
入口函数:
public static void main(String args[]){
Student student = new Student();
student.setAge(10);
student.setStudentName("xiaobai");
Glasses glasses = new Glasses();
glasses.setColor("red");
student.setGlasses(glasses);
try {
Student s1 = (Student) student.clone();
s1.setStudentName("xiaohei");
System.out.println("s1.color:"+s1.getGlasses().getColor());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
运行输出:
s1.color:red
通过以上实例,可以看出student中Glasses的color值被完全克隆给了s1,所以s1的Glasses的color也是red。