欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

深入分析Comparable與Comparator及Clonable三個Java接口

 更新時間:2022年05月10日 10:35:01   作者:xaiobit_hl  
接口不是類,而是對類的一組需求描述,這些類要遵從接口描述的統(tǒng)一格式進行定義,這篇文章主要為大家詳細介紹了Java的Comparable,Comparator和Cloneable的接口,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助

1.Comparable

這個接口是用來給對象數(shù)組來排序的

在我學接口之前我用的排序方法是Arrays.sort(),我發(fā)現(xiàn)單單靠之前所學知識并不能解決給對象數(shù)組排序的問題,后來學習過程中發(fā)現(xiàn)Comparable這一接口解決了我的疑惑,也感受到了這一接口的強大之處,但這也不是最好的,后續(xù)會說到,畢竟學知識是個循序漸進的過程嘛

首先,我們看一下我們之前學習時用的Arrays.sort

public class TestDemo {
    public static void main(String[] args) {
        int[] array = {1,3,6,2,4};
        Arrays.sort(array);
        System.out.println(Arrays.toString(array));
    }
}

它能將整形數(shù)組從小到大排序,,,下面我們再來看一下Arrays.sort給對象數(shù)組排序(錯誤示范)

class Student {
    public String name;
    public int age;
    public double score;
 
    public Student(String name, int age, double score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", score=" + score +
                '}';
    }
}
public class TestDemo {
    public static void main(String[] args) {
        Student[] students = new Student[3];
        students[0] = new Student("zhangsan",98,78.9);
        students[1] = new Student("lisi",38,48.9);
        students[2] = new Student("wangwu",18,88.9);
        Arrays.sort(students);
        System.out.println(Arrays.toString(students));
    }
}

當我們寫出這樣一個代碼的時候,我們會發(fā)現(xiàn)運行結(jié)果是個什么東西???

這時候不要慌,簡單分析一下報錯原因,我們可以看到它報了一個ClassCastException(類型轉(zhuǎn)換異常),根據(jù)后面的稍微能看懂的幾個英文(小編自己英文水平太差,所以只能看懂幾個),可以大概的知道是說Student不能轉(zhuǎn)換為java.lang包下的Comparable,這時候我們點進去看一下源碼,不要害怕看源碼,有時候我們往往只需要看懂一點就能明白錯誤的原因了

經(jīng)過粗略的分析if條件語句這一行,發(fā)現(xiàn)數(shù)組取下標呢,元素與元素之間都用compareTo來比較,這時候,我們發(fā)現(xiàn)其中的貓膩了,,,我們打開幫助手冊查一下Comparable,發(fā)現(xiàn)它是一個泛型接口,,并且它有一個抽象方法compareTo,這時候面紗就將要一層一層的揭開了

compareTo方法中這一大段畫,看到第一行我們就明白了,這東西可以幫我們解決數(shù)組對象的比較問題,所以我們要拿Student這個類去實現(xiàn)Comparable,并且實現(xiàn)compareTo方法,就能做到對象數(shù)組的排序了,看代碼:

class Student implements Comparable<Student>{
    public String name;
    public int age;
    public double score;
 
    public Student(String name, int age, double score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", score=" + score +
                '}';
    }
    @Override
    public int compareTo(Student o) {
        //return this.name.compareTo(o.name);
        //return this.age - o.age;
        return (int)(this.score-o.score);
    }
}

這時候Arrays.sort()就可以幫我們做到對象數(shù)組的排序了,在 sort 方法中會自動調(diào)用 compareTo 方法. compareTo 的參數(shù)是 Object , 其實傳入的就是 Student 類型的對象.

然后比較當前對象和參數(shù)對象的大小關(guān)系 (例如按score ).

  • 如果當前對象應排在參數(shù)對象之前 , 返回小于 0 的數(shù)字 ;
  • 如果當前對象應排在參數(shù)對象之后 , 返回大于 0 的數(shù)字;
  • 如果當前對象和參數(shù)對象不分先后 , 返回 0;

如果你對姓名的比較存在疑惑,比如:為什么name也可以調(diào)用compareTo方法這種類似的問題,因為name是String類型的,我建議你先看一下String的源碼,里面也實現(xiàn)了Comparable接口,以及重寫了compareTo方法,這里就不詳細介紹了,感興趣的小伙伴們可以嘗試一下哦,當然,我相信你們都是大佬,一看就懂哈哈

執(zhí)行程序,看運行結(jié)果,這下就能達到我們想要的效果了 

前面說了,這樣的代碼也不是最好的,存在局限性,我按分數(shù)來排序,那代碼就寫死了 ,那我以后想按姓名來排序,我又得回頭改???,以后進公司了,你的代碼做改變,影響其他人的代碼,那不得把你罵死,所以我們需要做進一步改進,引入Comparator接口

2.Comparator比較器

這個接口又叫比較器,那比較器又是個什么東西呢???下面我也是老套路啦,一步一步揭開這東西的面紗

為了解決Comparable接口的局限性,我們這個比較器完美的展現(xiàn)了實現(xiàn)效果,它也是一個泛型接口,同樣只有一個抽象方法需要重寫,下面看代碼:

class Student {
    public String name;
    public int age;
    public double score;
    public Student(String name, int age, double score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", score=" + score +
                '}';
    }
}
//比較器
class AgeComparator implements Comparator<Student> {
    @Override
    public int compare(Student o1, Student o2) {
        return o1.age - o2.age;
    }
}
class StringComparator implements Comparator<Student> {
    @Override
    public int compare(Student o1, Student o2) {
        return o1.name.compareTo(o2.name);
    }
}
class ScoreComparator implements Comparator<Student> {
    @Override
    public int compare(Student o1, Student o2) {
        return (int)(o1.score-o2.score);
    }
}
public class TestDemo {
    public static void main(String[] args) {
        Student[] students = new Student[3];
        students[0] = new Student("zhangsan",98,78.9);
        students[1] = new Student("lisi",38,48.9);
        students[2] = new Student("wangwu",18,88.9);
        /*AgeComparator ageComparator = new AgeComparator();
        Arrays.sort(students,ageComparator);
        StringComparator stringComparator = new StringComparator();
        Arrays.sort(students,stringComparator);*/
        ScoreComparator scoreComparator = new ScoreComparator();
        Arrays.sort(students,scoreComparator);
        System.out.println(Arrays.toString(students));
    }
}

通過這段代碼,我們發(fā)現(xiàn)比較器是真真正正的做到了,想按什么排序就按什么排序,在對類的侵入性以及代碼耦合度方面也算是不用太過擔心了

3.Clonable接口和深拷貝

Java 中內(nèi)置了一些很有用的接口 , Clonable 就是其中之一 .

Object 類中存在一個 clone 方法 , 調(diào)用這個方法可以創(chuàng)建一個對象的 " 拷貝 ". 但是要想合法調(diào)用 clone 方法 , 必須要先實現(xiàn) Clonable 接口 , 否則就會拋 CloneNotSupportedException 異常.

先來看一段代碼吧,我個人喜歡結(jié)合代碼看分析,這樣子就降低了云里霧里的可能性了,

class Student implements Cloneable{
    public int id = 1234;
    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                '}';
    }
    //重寫Object父類的clone()方法
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public class TestDemo {
    public static void main(String[] args) {
        Student student1 = new Student();
        try {
            Student student2 = (Student) student1.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
}

實現(xiàn)克隆的兩個條件(結(jié)合上面代碼):

1.這個對象可以被克隆,也就是這個Student類要實現(xiàn)這個Clonable接口

2.要在這個類中重寫父類Object的clone()方法

我們現(xiàn)在的代碼只是達到了這樣一個效果,,重頭戲還在后邊,因為我們的拷貝有時候遠遠不止于此,這種只能算是一個淺拷貝,那什么才算是深拷貝呢??? 請看下面的代碼:

class Money implements Cloneable{
    public double money = 19.9;
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
class Student implements Cloneable{
    public int id = 1234;
    public Money m = new Money();
    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                '}';
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public class TestDemo {
    public static void main(String[] args) throws CloneNotSupportedException {
        Student student1 = new Student();
        //為了代碼的好看,我這里不處理這個異常
        Student student2 = (Student) student1.clone();
        System.out.println(student1.m.money);
        System.out.println(student2.m.money);
        System.out.println("=========================");
        student1.m.money = 99.99;
        System.out.println(student1.m.money);
        System.out.println(student2.m.money);
    }
}

我現(xiàn)在在之前的代碼的基礎(chǔ)上添加了一個Money類,并且實例化Money的對象作為Student的成員,這時候克隆之后,改變我money的值,會是一個什么的效果呢???

先看運行結(jié)果吧,我就不兜圈子了 

我們發(fā)現(xiàn),這并不是我們想要的結(jié)果,我們想要的結(jié)果是,通過student2去改變money的值,它并不會影響student1中的money,而我們剛剛的代碼并沒有做到,它的效果圖如下:

那又如何做到深拷貝呢??這時我們就需要對我們剛才的代碼做一些改進了 

我們只需將原來的Student類中的Object的克隆方法改成下面這份代碼就能做到我們想要的效果:

@Override
    protected Object clone() throws CloneNotSupportedException {
        Student tmp = (Student) super.clone();//將id變量克隆一份,tmp指向它
        tmp.m = (Money) this.m.clone();//將m對象中的money變量克隆一份  tmp中的m指向它
        return tmp;
        //return super.clone();
    }

看到這個代碼先不要慌,如果注釋沒看明白,咱還有板書可以參照

其實分析起來也就那么回事

當我們tmp返回的時候,就把0x99給到了student2,克隆完成之后,tmp是局部變量,也就被回收了,,,就變成了下面這副摸樣:

這個時候,我們再去通過student2去改變我們的money,就不會影響student1中的money的值了,廢話不多說,運行結(jié)果為證

以上就是三個重要接口的全部分析了,下次再見?。?! 

到此這篇關(guān)于深入分析Comparable與Comparator及Clonable三個Java接口的文章就介紹到這了,更多相關(guān)Java Comparable Comparator Clonable內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論