匿名內部類
有時候我們需要臨時創建一個類和對象並且這個類無需在其他地方復用,就可以使用匿名內部類。
匿名內部類的好處是不需要單獨開一個類文件來編寫,也不需要類名稱,臨時使用很方便。
但是匿名內部類沒有名字也就沒有構造器,不能直接實例化。
同時匿名內部類只能實現一個接口,這一點從使用方式上就可以看出來。
實現接口的匿名內部類
匿名內部類多用於臨時實現一個接口,可以直接現場定義並實例化。
定義規則:
Interface in = new Interface() {
}
這里看上去是new一個接口實際上這里是語法糖,Java實際上是新建了一個實現該接口的類然后new這個類。
函數式接口
如果一個接口只定義了一個接口方法,那么該接口稱為函數式接口。
實際上類中的方法本質是一個函數,只實現一個方法的類使用起來就好像在使用這個函數。
函數式接口可以用@FunctionalInterface注解標注,編譯器會幫你檢測是否為一個函數式接口。
實現一個函數式接口的匿名內部類可以簡寫為Lambda表達式。
因為只實現一個方法,那么只要定義好了這個方法就等於定義好了這個匿名內部類。
那么對於這個方法的實現就可以抽出來,於是有了Lambda表達式。
Lambda表達式仍然是語法糖,Java后台根據表達式的定義創建了一個匿名內部類並實例化。
Lambda表達式只需要定義邏輯,甚至不需要聲明入參類型,因為這些都可以從接口中推斷出來。
函數式編程風格
函數式編程是說函數是第一公民,函數作為變量,可以接收函數,也可以返回函數。
Java沒有函數,只能傳入對象,所以使用匿名內部類來實現函數式編程的風格。
歷史上研究函數式編程的理論是Lambda演算,所以我們經常把支持函數式編程的編碼風格稱為Lambda表達式。
看一個例子
- 定義一個函數式接口
public interface Food {
String getFood(String name);
}
- 有一個方法要傳入實現該接口的對象
public class Demo4 {
// eat方法要傳入Food對象
public static void eat(Food f) {
String food = f.getFood("ham");
System.out.println("eating " + food);
}
// 匿名內部類
public static void main(String[] args) {
Demo4.eat(new Food() {
@Override
public String getFood(String name) {
return name;
}
});
// Lambda表達式
Demo4.eat(name -> {
return name;
});
// 如果只有return xxx 一行代碼,則可以簡寫
Demo4.eat(name -> name);
}
