0


【JAVASE】三大常用接口与深拷贝(Comparable,Comparator,Clonable)

初见乍惊欢,久处亦怦然

在这里插入图片描述
大家好,这里是新一,请多关照🙈🙉🙊。首先祝大家中秋团圆,在这中秋佳节,怎么不来一篇博客呢😋😋,接下来让我们了解一下JAVA三大常用接口和深拷贝吧。(以下结果均在IDEA中编译)希望在方便自己复习的同时也能帮助到大家。😜😜😜🥇🥈🥉

废话不多说,直接进入我们的文章。


文章目录


一.🥇 三大接口

此处我们以学生信息排序为例,给大家讲解一下这三大接口(Comparable
Comparator,Clonable)

1.1🥈 Comparable接口

我们知道JAVA中可以用Arrays.sort对数组进行排序,例如我们对下列数组进行排序

publicstaticvoidmain1(String[] args){int[] array ={1,21,3,14,5,16};Arrays.sort(array);System.out.println(Arrays.toString(array));}

其中的sort是根据数组元素的大小进行排序的,那么如果我们用Arrays.sort来排序复杂对象呢?如下

classStudentimplementsComparable<Student>{publicint age;publicString name;publicdouble score;publicStudent(int age,String name,double score){this.age = age;this.name = name;this.score = score;}@OverridepublicStringtoString(){return"Student{"+"age="+ age +", name='"+ name +'\''+", score="+ score +'}';}}publicclassTest{publicstaticvoidmain(String[] args){Student[] students =newStudent[3];
        students[0]=newStudent(14,"张三",78.9);
        students[1]=newStudent(13,"李四",86.9);
        students[2]=newStudent(12,"王麻子",99.5);System.out.println(Arrays.toString(students));Arrays.sort(students);System.out.println(Arrays.toString(students));}}

那么现在可以排序吗,那是肯定不行的,因为sort并不知道你要根据什么特性来排序,我们先来查看一下sort的底层代码

  1. 我们按住Ctrl并点击sort

在这里插入图片描述
2. 按住Ctrl点击legacyMerfeSort
在这里插入图片描述
3.按住Ctrl点击mergeSort
在这里插入图片描述
4. 此处我们发现这里有个compareTo函数,按住Ctrl并点击
在这里插入图片描述
我们发现这个函数是没有实现的,难道是意外吗?当然不是,我们再看看这个类
在这里插入图片描述
它是个Comparable接口,这个比较的函数CompareTo就需要我们自己来实现,如下:

//谁调用这个方法谁就是this@OverridepublicintcompareTo(Student o){returnthis.age - o.age;//根据年龄排序}

在这里插入图片描述
那么我们如果需要按名字来排序呢?

classStudentimplementsComparable<Student>{publicint age;publicString name;publicdouble score;publicStudent(int age,String name,double score){this.age = age;this.name = name;this.score = score;}@OverridepublicStringtoString(){return"Student{"+"age="+ age +", name='"+ name +'\''+", score="+ score +'}';}//谁调用这个方法谁就是this@OverridepublicintcompareTo(Student o){//return this.age - o.age;returnthis.name.compareTo(o.name);}}publicclassTest{publicstaticvoidmain(String[] args){Student[] students =newStudent[3];
        students[0]=newStudent(14,"张三",78.9);
        students[1]=newStudent(13,"李四",86.9);
        students[2]=newStudent(12,"王麻子",99.5);System.out.println(Arrays.toString(students));Arrays.sort(students);System.out.println(Arrays.toString(students));}}

没错,我们需要修改类里边的源码才能对排序特性进行修改,那么这样必然会存在一下问题,要知道,公司里边的源码是不能随便动的😎😎😎,因此,Comparable实现的接口有很大的缺陷 - 太嵌入

1.2🥈 Comparator接口

那么有没有更好的方法来实现我们的sort结构体排序呢?当然有,那就是我们的Comparator接口
我们同样按住Ctrl再点击Comparator
在这里插入图片描述
既然这个是个接口,我们就需要重写其中的方法compare,调用这个接口并重写这个方法的类我们就称为比较器

classAgeComparstorimplementsComparator<Student>{@Overridepublicintcompare(Student o1,Student o2){return o1.age - o2.age;}}classScoreComparstorimplementsComparator<Student>{@Overridepublicintcompare(Student o1,Student o2){return(int)(o2.score - o1.score);}}classNameComparstorimplementsComparator<Student>{@Overridepublicintcompare(Student o1,Student o2){return o1.name.compareTo(o2.name);}}

此即为学生这个对象排序的三个比较器,那么怎么调用呢?

classStudent{publicint age;publicString name;publicdouble score;publicStudent(int age,String name,double score){this.age = age;this.name = name;this.score = score;}@OverridepublicStringtoString(){return"Student{"+"age="+ age +", name='"+ name +'\''+", score="+ score +'}';}}classAgeComparstorimplementsComparator<Student>{@Overridepublicintcompare(Student o1,Student o2){return o1.age - o2.age;}}classScoreComparstorimplementsComparator<Student>{@Overridepublicintcompare(Student o1,Student o2){return(int)(o2.score - o1.score);}}classNameComparstorimplementsComparator<Student>{@Overridepublicintcompare(Student o1,Student o2){return o1.name.compareTo(o2.name);}}publicclassTest{publicstaticvoidmain(String[] args){Student[] students =newStudent[3];
        students[0]=newStudent(14,"张三",78.9);
        students[1]=newStudent(13,"李四",86.9);
        students[2]=newStudent(12,"王五",99.5);System.out.println(Arrays.toString(students));AgeComparstor ageComparstor =newAgeComparstor();ScoreComparstor scoreComparstor =newScoreComparstor();NameComparstor nameComparstor =newNameComparstor();Arrays.sort(students,nameComparstor);System.out.println(Arrays.toString(students));}}

我们只需要在main函数中new一个比较器对象,再将其加入到Arrays.sort方法中即可排序,****Comparator对类的侵入性非常弱 ,故在一般情况下推荐这个接口

1.3🥈 Clonable接口

Clonable 接口顾名思义它可以克隆我们的一个对象,在Object 类中存在一个 clone 方法, 调用这个方法可以创建一个对象的 “拷贝”. 但是要想合法调用 clone 方法, 必须要先实现 Clonable 接口, 否则就会抛出 CloneNotSupportedException 异常.

classPersonimplementsCloneable{publicint age;publicvoideat(){System.out.println("吃!");}@OverridepublicStringtoString(){return"Person{"+"age="+ age +'}';}@OverrideprotectedObjectclone()throwsCloneNotSupportedException{Person tmp =super.clone();return tmp;}}publicclassClonable{publicstaticvoidmain(String[] args)throwsCloneNotSupportedException{Person person =newPerson();
        person.age =99;Person person2 =(Person) person.clone();System.out.println(person2);System.out.println("===============");
        person2.age =199;System.out.println(person);System.out.println(person2);}}

此时我们会发现person2就是我们克隆的对象了,那么我们改变person2的值会影响person1吗,答案是否定的的,因为我们所实现的这个方法是所谓的深拷贝,它克隆了我们的这个对象,同样在堆区也就对了一份找个对象,两个对象互不影响

二.🥇 深拷贝

在上述用例中我们实现的方法即为深拷贝,但并不是Clonable这个接口是深拷贝,是我们实现的这个方法是深拷贝,取决于我们如何实现的方法,那么为什么呢?我们再给个用例

classMoneyimplementsCloneable{publicdouble m =12.5;}classPersonimplementsCloneable{publicint age;publicMoney money =newMoney();publicvoideat(){System.out.println("吃!");}@OverridepublicStringtoString(){return"Person{"+"age="+ age +'}';}@OverrideprotectedObjectclone()throwsCloneNotSupportedException{Person tmp =super.clone();return tmp;}}publicclassClonable{publicstaticvoidmain(String[] args)throwsCloneNotSupportedException{Person person =newPerson();Person person2 =(Person) person.clone();System.out.println(person.money.m);System.out.println(person2.money.m);System.out.println("===================");
        person2.money.m =99.99;System.out.println(person.money.m);System.out.println(person2.money.m);}}

此时会发现当我们改变拷贝对象时,原对象也发生变化,这就说明对象并未被拷贝,而只是引用被拷贝了一份,因此这就叫浅拷贝
我们也可以把它变成深拷贝。

classMoneyimplementsCloneable{publicdouble m =12.5;@OverrideprotectedObjectclone()throwsCloneNotSupportedException{returnsuper.clone();//拷贝引用对象}}classPersonimplementsCloneable{publicint age;publicMoney money =newMoney();//引用类型publicvoideat(){System.out.println("吃!");}@OverridepublicStringtoString(){return"Person{"+"age="+ age +'}';}@OverrideprotectedObjectclone()throwsCloneNotSupportedException{Person tmp =(Person)super.clone();
        tmp.money =(Money)this.money.clone();//调用方法拷贝对象return tmp;}}publicclassClonable{publicstaticvoidmain(String[] args)throwsCloneNotSupportedException{Person person =newPerson();Person person2 =(Person) person.clone();System.out.println(person.money.m);System.out.println(person2.money.m);System.out.println("===================");
        person2.money.m =99.99;System.out.println(person.money.m);System.out.println(person2.money.m);}}

此时我们发现,实现了深拷贝。

想对大家说的话

家人们,学到这里我们已经学习完了三大接口与深拷贝了,也在这里祝大家节日快乐🥳🥳🥳后续新一会持续更JAVA的有关内容,学习永无止境,技术宅,拯救世界!

在这里插入图片描述


本文转载自: https://blog.csdn.net/m0_73204758/article/details/126798280
版权归原作者 爱打酱油的新一 所有, 如有侵权,请联系我们删除。

“【JAVASE】三大常用接口与深拷贝(Comparable,Comparator,Clonable)”的评论:

还没有评论