點擊跳轉到原文
今天在看的代碼的時候,發現居然有個“實例化接口”的代碼,驚了,代碼如下:
public class testCollections {
public static void main(String[] args) {
ArrayList<Integer> list1 = new ArrayList<>();
list1.add(2);
list1.add(6);
list1.add(3);
list1.add(5);
list1.add(1);
//Collections.sort(list1);
Collections.sort(list1,new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1-o2;
}
});
System.out.println(list1);
}
}
但是我們明明一直了解的是接口和抽象類是不能new的,怎麼這裏就可以了,上網百度了了好久,關於這個問題解釋的,真的好少,最終找到一篇文章解釋:其實並沒有真正地實例化,new了一個實現接口的匿名內部類,然後new得到匿名內部類的對象再向上轉型爲它實現的接口(原始類型)
原文如下(其實我還是有點沒看懂,後面再找大神問下吧,暫時先記着)
先給大家看一個常用的代碼:
tv1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
});
注意到OnClickListener,Ctrl +左鍵進入源碼看到,
public interface OnClickListener {
/**
* Called when a view has been clicked.
*
* @param v The view that was clicked.
*/
void onClick(View v);
}
我們在學習Java基礎的時候知道,接口是不可以實例化的,那爲什麼上面OnClickListener可以new,這不得不讓我們問一下,到底接口能不能實例化。答案是:NO!
解釋一下,這是匿名內部類的寫法。new OnClickListener(){}其實並沒有真正地實例化,new了一個實現接口的匿名內部類,然後new得到匿名內部類的對象再向上轉型爲它實現的接口(原始類型)。這樣解釋可能還不夠,再讓大家看一段代碼:
class MyListener implements OnClickListener {
@Override
public void onClick(View v) {
}
}
tv1.setOnClickListener(new MyListener());
這樣寫大家就不會有任何的疑惑了,因爲不再看到接口被實例化了錯覺。我們看到只是一種省略的寫法,它實例化了一個匿名內部類,而這個類實現了一個接口。