Java的Comparable,Comparator和Cloneable三大接口詳解
1、比較器
①比較器的引入
a.首先,當(dāng)我們單一地比較某一種數(shù)據(jù)類型的數(shù)組時,可以直接用Arrays.sort()進(jìn)行實(shí)現(xiàn)

b.而當(dāng)我們同時含有多個參數(shù)時,并沒有告訴我們按照什么來進(jìn)行排序,此時,若是用Arrays.sort()就會出現(xiàn)報錯的情況

基于這種情況,我們了解到,若是要將自定義類型進(jìn)行大小比較 ,就要引入能夠?qū)崿F(xiàn)比較的接口,下面我們介紹Comparable和Comparator這兩種比較器
1.1Comparable接口
①實(shí)現(xiàn)Comparable接口的操作

②通過Comparable接口實(shí)現(xiàn)年齡的排序

③通過Comparable來實(shí)現(xiàn)名字的排序(注意名字是引用類,比較時應(yīng)該是用compareTo()來進(jìn)行)

④升序降序
由于最終是利用的Arrays.sort()進(jìn)行的比較,該方法底層是升序的操作,若是想轉(zhuǎn)換為降序,只需要將重寫的compareTo()方法中兩項互換位置即可

變?yōu)榻敌蚝蟠a運(yùn)行結(jié)果:

⑤缺點(diǎn)?。。?/strong>
Comparable對類的傾入性很強(qiáng)。由上面我們可知,要想比較新的類型就要更改compareTo()中的類型重新進(jìn)行比較,這個在以后的工作中極大可能會使整個代碼出現(xiàn)邏輯問題,可讀性問題,因此我們引入下一類很靈活,傾入性不強(qiáng)的Comparator接口
⑥整體代碼如下:
import java.util.Arrays;
class Student implements Comparable<Student> {
public int age;
public String name;
public double score;
public Student(int age,String name,double score){
this.age=age;
this.name=name;
this.score=score;
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
", score=" + score +
'}';
}
public static void main3(String[] args) {
Student student1=new Student(12,"張三",98.0);
Student student2=new Student(18,"李四",97.9);
//if(student1.compareTo(student2)>0)返回1;根據(jù)下面的方法進(jìn)行進(jìn)一步的返回
System.out.println(student1.compareTo(student2));
}
public static void main(String[] args) {
Student []student=new Student[3];
student[0]=new Student(36,"zhangsan",98.0);
student[1]=new Student(18,"lisi",97.9);
student[2]=new Student(27,"wangwu",65.3);
System.out.println(Arrays.toString(student));
Arrays.sort(student);
System.out.println(Arrays.toString(student));
}
public static void main1(String[] args) {
int []array=new int []{2,5,3,6,8};
System.out.println(Arrays.toString(array));
Arrays.sort(array);
System.out.println(Arrays.toString(array));
}
@Override
//誰調(diào)用這個方法,誰就是this
public int compareTo(Student o) {
//return this.age-o.age;
return o.name.compareTo(this.name);
}
}1.2Comparator接口
①實(shí)現(xiàn)Comparable接口的操作:

②通過該接口實(shí)現(xiàn)的姓名的比較:

③升序降序

執(zhí)行后的結(jié)果:

④優(yōu)點(diǎn)
靈活,對類的傾入性不強(qiáng)
⑤整體代碼如下:
import java.util.Arrays;
import java.util.Comparator;
class Student {
public int age;
public String name;
public double score;
public Student(int age, String name, double score) {
this.age = age;
this.name = name;
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
", score=" + score +
'}';
}
}
class AgeComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.age-o2.age;
}
}
class ScoreComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return (int)(o1.score-o2.score);
}
}
class NameComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.name.compareTo(o2.name);
}
}
public class Test {
public static void main2(String[] args) {
Student students1 = new Student(1,"bit",98.9);
Student students2 = new Student(2,"abc",88.9);
/* if(students1.compareTo( students2) > 0) {
}*/
//System.out.println(students1.compareTo( students2));
AgeComparator ageComparator = new AgeComparator();
System.out.println(ageComparator.compare(students1,students2));
}
public static void main(String[] args) {
Student[] student = new Student[3];
student[0] = new Student(12,"lisi",98.9);
student[1] = new Student(6,"zangwu",88.9);
student[2] = new Student(18,"whangsan",18.9);
System.out.println(Arrays.toString(student));
AgeComparator ageComparator = new AgeComparator();
ScoreComparator scoreComparator = new ScoreComparator();
NameComparator nameComparator = new NameComparator();
Arrays.sort(student,nameComparator);//默認(rèn)是從小到大的排序
System.out.println(Arrays.toString(student));
}
public static void main1(String[] args) {
int[] array = {1,21,3,14,5,16};
System.out.println(Arrays.toString(array));
Arrays.sort(array);
System.out.println(Arrays.toString(array));
}
}2、Cloneable接口
①如何實(shí)現(xiàn)Cloneable接口:
Object 類中存在一個 clone 方法, 調(diào)用這個方法可以創(chuàng)建一個對象的 "拷貝". 但是要想合法調(diào)用 clone 方法, 必須要先實(shí)現(xiàn) Clonable 接口, 否則就會拋出 CloneNotSupportedException 異常。
a.實(shí)現(xiàn)Cloneable接口

b.重寫Cloneable方法

c.拋異常,強(qiáng)制類型轉(zhuǎn)換

②面試中常問問題:
你知道Cloneable接口嗎?為什么它是一個空接口,它有什么作用呢?
空接口,標(biāo)志接口,代表這個類是可以被克隆的
③克隆的原理圖:

④整體代碼的實(shí)現(xiàn):
class Person implements Cloneable{
public int age;
public void eat(){
System.out.println("吃!");
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class TestDemo {
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person();
person.age=13;
Person person2=(Person)person.clone();
System.out.println(person2);
System.out.println(person);
System.out.println("===========");
person2.age=14;
System.out.println(person);
System.out.println(person2);
}
}2.1深拷貝和淺拷貝
①深淺拷貝:
決定是深拷貝還是淺拷貝,并不是方法的用途,而是代碼的實(shí)現(xiàn)
②淺拷貝示例


淺拷貝代碼如下:
class Money implements Cloneable{
public double m = 12.5;
}
class Person implements Cloneable{
public int age;
public Money money = new Money();
public void eat() {
System.out.println("吃!");
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
Person tmp = (Person)super.clone();
return tmp;
}
}
public class TestDemo {
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person();
Person person2 = (Person)person.clone();
System.out.println(person.money.m);
System.out.println(person2.money.m);
System.out.println("=====================");
person2.money.m = 98.5;
System.out.println(person.money.m);
System.out.println(person2.money.m);
}
}③深拷貝示例:(將tmp中的money也進(jìn)行拷貝)

深拷貝代碼如下:
class Money implements Cloneable{
public double m = 12.5;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Person implements Cloneable{
public int age;
public Money money = new Money();
public void eat() {
System.out.println("吃!");
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
Person tmp = (Person)super.clone();
tmp.money = (Money) this.money.clone();
return tmp;
//return super.clone();
}
}
public class TestDemo {
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person();
Person person2 = (Person)person.clone();
System.out.println(person.money.m);
System.out.println(person2.money.m);
System.out.println("=====================");
person2.money.m = 98.5;
System.out.println(person.money.m);
System.out.println(person2.money.m);
}
}總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Java Poi 在Excel中輸出特殊符號的實(shí)現(xiàn)方法
這篇文章主要介紹了Java Poi 在Excel中輸出特殊符號的實(shí)現(xiàn)方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-07-07
Spring?Boot異步線程間數(shù)據(jù)傳遞的四種方式
這篇文章主要為大家介紹了Spring?Boot異步線程間數(shù)據(jù)傳遞的四種方式詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01
RecyclerChart動態(tài)屬性圖標(biāo)聯(lián)動數(shù)據(jù)動態(tài)加載詳解
這篇文章主要為大家介紹了RecyclerChart動態(tài)屬性圖標(biāo)聯(lián)動數(shù)據(jù)動態(tài)加載詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
Java父線程(或是主線程)等待所有子線程退出的實(shí)例
下面小編就為大家分享一篇Java父線程(或是主線程)等待所有子線程退出的實(shí)例,具有很好的參考價值,希望對大家有所幫助2017-11-11
使用springboot在工具類中讀取配置文件(ClassPathResource)
這篇文章主要介紹了使用springboot在工具類中讀取配置文件(ClassPathResource),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-08-08
SpringBoot使用redis實(shí)現(xiàn)session共享功能
這篇文章主要介紹了pringboot項目使用redis實(shí)現(xiàn)session共享,文中通過代碼示例講解的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-05-05
spring boot使用i18n時properties文件中文亂碼問題的解決方法
這篇文章主要介紹了spring boot使用i18n時properties文件中文亂碼問題的解決方法,需要的朋友可以參考下2017-11-11

