1. 程式人生 > >實現匿名內部類Comparator介面,沒有重寫所有抽象方法引起的思考

實現匿名內部類Comparator介面,沒有重寫所有抽象方法引起的思考

      這幾天在學習關於jdk8的一些知識,在看到講解lambda表示式的引入原因時,舉了一個匿名類的例子,並進一步引入lambda表示式,因為lambda表示式比匿名類更簡潔明瞭易懂。

匿名類寫法如下:

inventory.sort(new Comparator<Apple>() { 
    public int compare(Apple a1, Apple a2){ 
        return a1.getWeight().compareTo(a2.getWeight());
    } 
}); 

inventory是一個List<Apple>。

        這時候大家思考一個問題,Comparator介面有兩個抽象方法,一個是compare,另一個是equals方法,而寫這個匿名內部類時,怎麼沒有重寫equals方法呢,也沒有報錯。

       我在網上查了相關解釋如下:寫匿名類別類,系統給我們自動建立了實現類(這個大家都知道),這個實現類裡自動重寫了所有抽象方法,只是方法體是空的。我雖然只重寫了部分方法,但是其他方法已經被臨時類重寫了只不過是空方法而已!

      聽這個解釋還是比較信服的,但是我想一探究竟,到底是不是這麼回事,後來我自己寫了測試一下。

竟然發現和上面的解釋有所不同。因為我利用反編譯工具開啟系統生成那個介面的實現類,發現裡面並沒有重寫equals方法。這就奇怪了,為什麼沒有重寫equals方法還不報錯呢?後來想了想明白了,原因是所有類都繼承Object類,而Object類裡有實現equals方法,那麼那個系統生成的實現類肯定也有這個equals方法啊,所以也就是重寫了Comparator介面的equals方法。這麼一來,網上那個解釋是不對的啊。

反編譯工具開啟系統建立的實現類沒有equals方法的截圖如下:

       為了驗證網上的說法是否正確,我有自己建了一個介面,內有兩個抽象方法,然後匿名類類實現一個抽象方法,結果編譯時報錯,說是沒有重寫另一個方法。這就驗證了網上的說法是錯誤的。

錯誤貼圖如下:

     寫在後面的話,首先我是在jdk1.8寫測試的,不知道在jdk1.6寫的是否網上的說法成立?各位有測試的可以留言告知。

在jdk1.8下,匿名內部類的寫法必須重寫介面所有抽象方法,系統建立的實現類不會自動建立所有抽象方法。

現在把所有程式碼貼在下面,供大家測試

import java.util.*;
public class MyTest{
    
    public static void main (String[] args){
        List<Student> list = new ArrayList<Student>();
        list.add(new Student(1,"aa"));
        list.add(new Student(2,"bb"));
        
        list.sort(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {

                return o1.getNum().compareTo(o2.getNum());
            }
        });
        
        //匿名內部類寫法,只重寫test1,未重寫test2,報錯
        method1(new MyInterface(){
            @Override
            public int test1(){
                System.out.println("aaaaaa");
                return 2;
            }
            
            
        });
        
    }
    
    public static void method1(MyInterface myInterface){
        System.out.println("1231231321");
    }
}

//自定義的介面,有兩個抽象方法
interface MyInterface{
    
    int test1();
    
    void test2();
}

 class Student{
    
    private Integer num;
    
    private String name;
    
    Student(){}
    
    Student(Integer num,String name){
        this.num = num;
        this.name = name;
    }
    
    public void setNum( Integer num){
        this.num = num;
    }
    
    public Integer getNum(){
        return this.num;
    }
    
    public void setName(String name){
        this.name = name;
    }
    
    public String getName(){
        return this.name;
    }
}