JAVA对象的克隆

 克隆:使用已有变量的数据创建一个新的变量的过程叫克隆,也称为复制。

        对于基本数据类型的克隆,我们可以通过赋值运算符 “ = ” 实现变量的克隆。而且修改原有变量的数据不会影响克隆对象的数据。

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值