Java:接口应用(Clonable 接口和深拷贝)

目录

  • 1.引例
  • 2.Object中clone方法的实现
  • 3.Cloneable接口讲解
  • 4.深拷贝和浅拷贝
    • 4.1浅拷贝
    • 4.2深拷贝

1.引例

Java 中内置了一些很有用的接口, Clonable 就是其中之一.
Object 类中存在一个 clone 方法, 调用这个方法可以创建一个对象的 “拷贝”. 但是要想合法调用 clone 方法。必须要先实现 Clonable 接口。 否则就会抛出异常.
( CloneNotSupportedException )
如下所示,当我们要克隆一个我们已经实例化的Student类该怎么去实现呢?

class Student{
    private int age;
    public Student(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                '}';
    }
}
public class Test {
    public static void main(String[] args) {
        Student student1=new Student(10);
    }
}

首先,我们要知道Java中所有的类都继承Object类
当我们找到Object类的原码时,我们会发现一个clone()方法
在这里插入图片描述
那我们可能会想:既然所有的类都继承Object类,那当我们要克隆student1,直接通过student1.clon去调用这个克隆方法来实现克隆操作,但是真正去实现的时候就会发现以下问题:我们找不到这个方法。
在这里插入图片描述

2.Object中clone方法的实现

在这里插入图片描述
为什么找不到Object类中的clone方法呢,通过原码我们能看到Object类中clone方法由protected修饰
protected:同包下可以访问,不同包只有子类能访问
所以我们进行第一步,方法的重写
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
重写后可以引用clone方法了,但是我们会发现还是报错,因为引用的clone方法是父类的。
当我们要将它传给子类我们就要进行第二步:强制转换
在这里插入图片描述
强制转换后还是报错,这样我们就需要进行第三步:(涉及异常知识,后面再进行补充)

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

在这里插入图片描述

这时解决完异常问题后,当我们真正进行运行时还是会报错,这样我们就要进行第四步:实现Cloneable接口
在这里插入图片描述
在这里插入图片描述
完成以上四步后就可以成功完成clone了。
完整代码

class Student implements Cloneable{
    private int age;
    public Student(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                '}';
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        Student student1=new Student(10);
        Student student2=(Student)student1.clone();
        System.out.println(student2.toString());
    }
}

输出结果
在这里插入图片描述

3.Cloneable接口讲解

通过原码可以发现Cloneable里面什么也没有,是一个空接口(也叫标记接口)。
在这里插入图片描述

4.深拷贝和浅拷贝

4.1浅拷贝

class Money{
    public double money=12.5;
}
class Student implements Cloneable{
    private int age;
    public Money m=new Money();
    public Student(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                '}';
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        Student student1=new Student(10);
        Student student2=(Student)student1.clone();
        System.out.println(student2.toString());
    }
}

我们在上面的代码中加入了Money类并且在Student类中实例化了一个Money。
这时我们再进行克隆如下图所示
在这里插入图片描述
当我们对student1进行可能时money并没有也克隆一份,这样就是浅拷贝。举例如下:
在这里插入图片描述
在这里插入图片描述
我们只是改变了student2的money,但是student1的money也跟着改变了。

4.2深拷贝

class Money implements Cloneable{
    public double money=12.5;
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
class Student implements Cloneable{
    private int age;
    public Money m=new Money();
    public Student(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                '}';
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Student temp=(Student)super.clone();
        temp.m= (Money)this.m.clone();
        return temp;
    }
}
public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        Student student1=new Student(10);
        Student student2=(Student)student1.clone();
        System.out.println(student1.m.money);
        System.out.println(student2.m.money);
        System.out.println("================");
        student2.m.money=100;
        System.out.println(student1.m.money);
        System.out.println(student2.m.money);
    }
}

我们使Money类也重写clone方法,并对Student类中的clone方法进行了改动,来实现深拷贝
在这里插入图片描述
举例如下
在这里插入图片描述
在这里插入图片描述

上一篇:机器学习笔记 - 深度学习遇到超大图像怎么办?使用 xT 对极大图像进行建模论文简读


下一篇:windows渗透信息收集