克隆:使用已有变量的数据创建一个新的变量的过程叫克隆,也称为复制。
对于基本数据类型的克隆,我们可以通过赋值运算符 “ = ” 实现变量的克隆。而且修改原有变量的数据不会影响克隆对象的数据。
int x = 10;
int y = x;
System.out.println("x的值:" + x +" ;y的值: "+y);
x=20;
System.out.println("x的值:" + x +" ;y的值: "+y);
运行结果:
但是对于对象的克隆就不可以使用简单的赋值运算符来操作了。
比如:我们创建一个空类,里面没有任何的属性和方法。
public class Student{
}
我们在main()方法中new一个Student对象student1,并且将这个对象赋值给Student student2。通过“ == ”判断两者是否是同一个对象。
public static void main(String[] args) {
Student student1 = new Student();
Student student2 = student1;
System.out.println(student1 == student2);
}
返回结果:true
我们都知道,引用对象的内存空间分两种,一种是栈内存,一种是堆内存。
student1中保存的只是 Stuent对象在堆内存中的地址,通过赋值运算符“=”,只是将堆内存的地址复制给了student2,student1和student2指向的还是同一个对象。
如何实现对象的克隆?
在Object类中有个clone()方法可以帮助我们实现对象的克隆,我们都知道Object类是所有类的父类,正常来说所有的对象都可以实现克隆,但是事实却不是这样的,在Object类中关于clone()方法的定义描述是这样的:
/* @throws CloneNotSupportedException if the object's class does not
* support the {@code Cloneable} interface. Subclasses
* that override the {@code clone} method can also
* throw this exception to indicate that an instance cannot
* be cloned.
* @see java.lang.Cloneable
*/
protected native Object clone() throws CloneNotSupportedException;
描述:如果该类不是Cloneable的子类或者没有覆写clone()方法,那么就会抛出CloneNotSupportedException异常。
所以,要实现对象的克隆我们需要满足两个条件
(1)实现Cloneable接口(该接口只是一个标记接口,不含任何方法)
(2)重写clone()方法,调用supper.clone();
克隆分为浅克隆和深克隆
浅克隆(ShallowClone)
class Student implements Cloneable{
private int age ;
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return this.age;
}
@Override
protected Object clone() {
Student stu = null;
try {
stu = (Student)super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
return stu;
}
}
public class Main {
public static void main(String[] args) {
Student student1 = new Student();
student1.setAge(20);
Student student2 =(Student) student1.clone();
System.out.println("student1的age属性值:"+student1.getAge() +" student2的age属性值:"+student2.getAge());
}
}
程序结果:
student1的age属性值:20 student2的age属性值:20
此时我们修改student1的age属性,在打印一次两个对象的age值。
student1.setAge(30);
System.out.println("student1的age属性值:"+student1.getAge() +" student2的age属性值:"+student2.getAge());
程序执行结果:
student1的age属性值:30 student2的age属性值:20
此时发现当我们修改了student1.age的值时,student2.age的属性值依然没有变化,说明student1和student2是两个不同的对象,只是student2的初始值是从student1中获取到的。
深克隆
那么如果此时Student对象中增加了一个Teacher对象,情况又如何呐?
针对以上程序做一下修改:
class Student implements Cloneable{
private int age ;
private Teacher teacher;
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
public Teacher getTeacher() {
return teacher;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return this.age;
}
@Override
protected Object clone() {
Student stu = null;
try {
stu = (Student)super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
return stu;
}
}
class Teacher{
private int age ;
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
}
public class Main {
public static void main(String[] args) {
Teacher teacher = new Teacher();
teacher.setAge(40);
Student student1 = new Student();
student1.setTeacher(teacher);
Student student2 =(Student) student1.clone();
System.out.println("student1的teacher属性值:"+student1.getTeacher().getAge() +" student2的teacher属性值:"+student2.getTeacher().getAge());
}
}
结果:
student1的teacher属性值:40 student2的teacher属性值:40
咋一看没问题,但是真的么问题吗?
我们修改一下Teacher对象的age的值,再来看一下;
teacher.setAge(50);
System.out.println("student1的teacher属性值:"+student1.getTeacher().getAge() +" student2的teacher属性值:"+student2.getTeacher().getAge());
结果
student1的teacher属性值:50 student2的teacher属性值:50
不仅student1的属性发生了改变,连student2的属性值也发生了改变,证明student1的theacher和student2的teacher对象是同一个
那么,如何实现Teacher对象的克隆呐?
我们知道对象的克隆需要实现两个条件:1、实现Clonable接口;2、覆写clone()方法。而我们的Theacher也是一个对象,同样也要满足这两个条件。
针对以上程序做一下修改:
1、Teacher类实现Cloneable接口
class Teacher implements Cloneable{
private int age ;
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
@Override
protected Object clone() {
Teacher teacher = null ;
try {
teacher = (Teacher) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
return teacher;
}
}
2、Student类的clone()方法中,调用teacher对象的clone(),并将返回对象重新赋值给Student.teacher属性。
protected Object clone() {
Student stu = null;
try {
stu = (Student)super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
stu.teacher = (Teacher) teacher.clone();
return stu;
}
执行结果:
student1的teacher属性值:50 student2的teacher属性值:40