Bootstrap

java实现简单的克隆(调用Object的clone方法和浅拷贝,深拷贝)

目录

浅拷贝

浅拷贝过程和问题解析:

浅拷贝完整代码

结果:

浅拷贝与深拷贝区别详解

实现深拷贝

深拷贝完整代码:


浅拷贝

目标:通过调用object的clone方法将对象student1的内容拷贝到student2中去

省流总结:浅拷贝的常见问题:

1:Object的clone方法是protected修饰需要在克隆类中重写

2:编译时异常/受查异常

3:向下转型时需要强制类型转换

4:克隆类需要设置标记接口

浅拷贝过程和问题解析:

首先我们有一个Student对象并给他实例化

package csda克隆代码示范;
class Student{
    public int age;

    public Student(int age) {
        this.age = age;
    }
}
public class Test {
    public static void main(String[] args) {
        Student student1 = new Student(30);//待拷贝内容

    }
}

因为Java中所有的类都会默认继承Object父类,所以我们最简单直接的想法是直接通过student1调用Object的clone方法并用student2接收

 不幸的是,student1无法调用clone方法——————————。。。。。。。。。。。。

为什么呢?

我们查看来查看object的clone方法的原码(双击shift键搜索object然后回车,在左侧Structure中找打clone方法)

 clone方法如下:

 真相大白!!!!

Object中clone方法是用protected修饰的!!!所以无法通过不同包的非子类来调用;

同时我们发现clone方法确实会返回一个满足我们拷贝需求的对象,并且是Object类型的(后面要用)。

那怎么解决这个问题呢?

答案是在我们的Student类中重写一个clone方法并在这个方法中用super调用Object类的clone方法、

快捷方法:右键+generate+Override Methdos+clone

 结果:

 @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

 同时,student1中可以点出clone方法

 但是,这是我们发现clone方法还是错的。。。。。。。

这里的错误是受查异常/编译时异常,解决方法:鼠标放在clone上,同时alt+回车

 选择第一个选项。

令人悲伤的:

 红线变长了。。。。。

又一个错误出现。

我们回忆一下,刚刚clone方法的原码。。。。。

Object的clone方法会返回一个Object类型的对象给student中重写的clone方法,然后我们用student2来给这个对象实例化。

总结一下:我们将父类的Object类交给了子类Student。这是一个什么过程?——向下转型

向下转型需要将我们的父类强制类型转换成子类类型:

     Student studen2 = (Student)student1.clone();

然后运行。你以为这就结束了?

。。。。。。。。。。。。。。。。

别急,还有最后一个问题需要解决(真的是最后一个)

上面的报错是:不支持克隆

我们需要在Student类继承一个克隆接口

class Student implements Cloneable{
}

 这个接口是一个空接口也叫标记接口,证明当前类是可以被克隆的。

浅拷贝完整代码


package csda克隆代码示范;
class Student implements Cloneable{
    public int age;//需要克隆的成员变量

    //构造函数
    public Student(int age) {
        this.age = age;
    }

    @Override//重写的clone方法
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();//调用Object的clone方法
    }

}
public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        Student student1 = new Student(30);
        Student student2 = (Student)student1.clone();
        System.out.println(student1.age);
        System.out.println(student2.age);


    }
}

结果:

浅拷贝与深拷贝区别详解

我们现在写一个Number类,给Student类中设置一个Number类型的成员变量,并在Student的构造方法中给其实例化。

接下来在Test类中先输出student1和student2的值,然后修改student2的m的num值,发现student1中的m的num值也随之改变


package csda克隆代码示范;
//
class Number{
    int num;
}
class Student implements Cloneable{
    public int age;
    public Number m;//在原来的代码的基础上添加一个Number类型的成员变量,名称为m

    public Student(int age) {
        this.age = age;
        this.m = new Number();//实例化
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

}
public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        Student student1 = new Student(30);
        Student student2 = (Student)student1.clone();
        System.out.println(student1.m.num);
        System.out.println(student2.m.num);
        student1.m.num = 1;//更改student2的m的num的值
        System.out.println(student1.m.num);
        System.out.println(student2.m.num);




    }
}

结果:

 为什么我们更改了student2的m的num值,student1的m的num值也改变了?

浅拷贝图解:

 当我们在student类中实例化一个m类后:

 我们的super.clone克隆了student1中的内容,所以我们在student2中也实例化了一个Number类型的m对象,它们都引用了类Number,所以我们在通过student2更改m的值之后,student1的m的num值也会改变。

用上述代码我们在克隆一个对象(这个对象里还有一个对象)时,对象里的对象并不满足拷贝,这种情况我们就称作浅拷贝。

那怎么改成深拷贝呢?

实现深拷贝

1:在克隆对象里的对象对应的类重写克隆方法并添加标记接口(本文中时Number类)

class Number implements Cloneable{
    int num;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

2:设置一个过渡的类接收clone返回的克隆对象并返回tmp

  protected Object clone() throws CloneNotSupportedException {
        Student tmp = (Student)super.clone();
        tmp.m = (Number)this.m.clone();
        return  tmp;
    }

深拷贝完整代码:


package csda克隆代码示范;
class Number implements Cloneable{
    int num;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
class Student implements Cloneable{
    public int age;
    public Number m;

    public Student(int age) {
        this.age = age;
        this.m = new Number();
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Student tmp = (Student)super.clone();
        tmp.m = (Number)this.m.clone();
        return  tmp;
    }

}
public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        Student student1 = new Student(30);
        Student student2 = (Student)student1.clone();
        System.out.println(student1.m.num);
        System.out.println(student2.m.num);
        student2.m.num = 1;
        System.out.println(student1.m.num);
        System.out.println(student2.m.num);


    }
}

;