Cloneable接口 和 深拷贝
💐文章导读
这篇文章就为大家讲讲什么是Cloneable接口,接口的用法以及什么是深拷贝和浅拷贝,如果有不足的地方,还望读者在评论区提出!!!
上篇文章讲过用Comparable接口进行对象比较,和一个Comparator比较,但是许多有趣的接口还有好多,请让我持续给您讲解,假如,你写了一个重要的代码,但是很害怕万一万一数据丢了怎么办?这时,就有人说了,我直接复制存储一份不就行了么😂,对,没错,是这样的😂,现在就要讲一个和复制功能一样的有趣接口:
🍁Cloneable接口
下面,我会根据下面的代码来对Cloneable接口进行讲解:
public class Student implements Cloneable{//实现接口
int age = 10;
//重写clone方法
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
'}';
}
public static void main(String[] args) throws CloneNotSupportedException {
Student student1 = new Student();
Student student2 = (Student)student1.clone();
System.out.println(student1.toString());
System.out.println(student2.toString());
}
}
下面将针对上面的代码一段一段的讲解,请拿好你的小板凳认真坐好啦!!!
下面一段一段的代码可能与上面有一点点的不同,那是因为上面是处理过后的完美代码,下面讲解的代码是没有经过处理的,根据没有处理过的代码一步一步带你学会clone()方法,最后就会称为完美的代码!!!
可以看到,当调用clone()方法时,结果报出了一个异常表示不支持克隆;下面就解决这第一个异常(第一个异常说明这里不止一个异常😂);
我们点击去clone()方法,看看它的是如何实现的;
可以看到,clone方法是属于object类的,但是object类不是所有类的父类么,那Student类也应该是Object类的子类呀,在子类中调用父类中的方法,为什么没办法调用呢?
第一个异常:
想要在子类中调用父类的方法,就要通过super进行调用,那么就通过在子类中重写父类的方法,调用重写的clone方法;
当重写这个方法后发现,它还是报错的,那怎么回事呢?来接着看!
当把鼠标放在红线位置时发现,有一个添加异常到方法签名,下面就点击一下,发现这个红线不仅没消失还变长了😅,然后在main方法后添加了一行这个东西,这个异常将在Java异常文章中进行讲解,这里简单提一下,这里表示,在main函数中可能会抛出一个异常,而这个异常如果在方法这里不进行处理的话,就会交给方法的调用者处理,就这样一直向上推,最后交给了jvm进行处理,jvm就会报出错误,终止程序;
那这个异常是怎么回事呢?是因为:当student1调用clone方法时,因为clone方法的返回类型是Object类型的,而Object类是Student的父类,把父类对象赋值给子类进行了向下转型,所以要进行强制类型转化;
看,这样就没有红线啦,那么现在就运行起来!!!
结果运行时还报异常,我就想要拷贝一下还没完没了了是吧,不要着急😂,解决完这个异常,就完事了,可以看到这里表示的是Student不能被拷贝,那么是因为我们还要去实现Cloneable接口;
当实现完Cloneable接口后,进入这个接口发现,这个接口是空的,那么这个接口有什么用呢?因为啊,这个接口也叫作标记接口,表示这个对象可以被克隆,如果不实现这个对象的话,就没办法进行克隆,没办法,谁让人家就是这么规定的呢😁
那么 下面就可以正常运行了
以上就是clone方法的使用,你学废了么!!!
不要打瞌睡,下面就要上硬货啦,既然学过了拷贝,那么就来拓展一下什么是深拷贝吧!!!
🍁深拷贝
下面是完美的代码,没有错误的,下面如果我讲的代码如果有什么不一样的,不要奇怪,那是因为我要给你讲呀!最后都会再回到下面的代码中的。我会一步一步的将下面的代码进行讲解:
class Grade implements Cloneable{
int grade = 60;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Student implements Cloneable{
int age = 10;
Grade g;
public Student() {
this.g = new Grade();
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
Student tmp = (Student) super.clone();
tmp.g = (Grade) this.g.clone();
return tmp;
}
public static void main(String[] args) throws CloneNotSupportedException {
Student student1 = new Student();
Student student2 = (Student) student1.clone();
System.out.println(student1.toString());
System.out.println(student2.toString());
System.out.println("===========================");
//对student2中g的grade进行修改
student2.g.grade = 90;
System.out.println(student1.g.grade);
System.out.println(student2.g.grade);
}
}
请看我慢慢给你讲解:
然而结果并不理想,它把两个对象里的grade都改了,哎!我不是进行了拷贝么,怎么会改一个把两个全都改了呢?上面之所以是这种情况是因为,现在并没有构成深拷贝,而是下图这种情况,请看下面图解:
它只是对Student对象中的内容进行了一份拷贝,但是并没有对,对象中的对象中的内容进行拷贝也就是grade=60;这种情况就是浅拷贝!那想要进行深拷贝该怎么操作呢?下面请看我讲解:
以上就是讲解,下面将根据上面的讲解做的一个配图;
就仅仅对clone方法里面的代码添加了三行就构成了深拷贝,所以是不是很神奇呢!!!