參考書籍:《Java 8函數(shù)式編程》
Java8帶來最大的改變就是Lambda表達(dá)式了,廢話不多說,開始正題~
定義:Lambda表達(dá)式是一個匿名方法,將行為像數(shù)據(jù)一樣傳遞。
以前我們的習(xí)慣都是傳遞基本類型和對象類型的數(shù)據(jù),現(xiàn)在可以傳遞行為了~常見結(jié)構(gòu):
BinaryOperator<Integer> add = (x, y) -> x + y;
本來是這樣寫的BinaryOperator<Integer> add = (Integer x, Integer y) -> x + y;但因為類型推斷,編譯器會根據(jù)前面的泛型<Integer>自動推斷出后面的參數(shù)類型,所以可以簡寫成上面的樣子。
如果只有一個參數(shù)的Lambda表達(dá)式,括號都可以省略,直接寫成x->x>5;
根據(jù)參數(shù)個數(shù)和返回值的不同,Java8中都有對應(yīng)的函數(shù)式接口。具體的接口有哪些暫時不談。
事實(shí)上Java7中就已經(jīng)存在了類型推斷,比如定義一個List<Integer> list = new ArrayList<>();右邊無需再寫類型。方法引用的關(guān)鍵字
::,用來傳遞方法或者構(gòu)造函數(shù)引用。
比如上面的表達(dá)式可以寫為:BinaryOperator<Integer> add = Integer::sum;
引用構(gòu)造方法就可以寫成Class::new函數(shù)式接口:僅僅只有一個抽象方法的接口,類上有注解
@FunctionalInterface標(biāo)示。
接收Lambda表達(dá)式的類全部都是函數(shù)式接口。上面的BinaryOperator就是如此。
事實(shí)上是可以有多個抽象方法,只不過其他抽象方法必須是Object類中的public方法,比如equals方法。因為接口都有實(shí)現(xiàn)類,而類都繼承Object,最終都有equals方法,只不過接口中定義equals方法,會強(qiáng)制你實(shí)現(xiàn)equals方法罷了~
另外除了抽象方法,還可以有靜態(tài)方法,默認(rèn)方法(Java8新增的關(guān)鍵字default),所以接口再也不是只有抽象方法了。
新增默認(rèn)方法,只是為了向后兼容,比如List接口中新增抽象方法,所有的實(shí)現(xiàn)類都要去實(shí)現(xiàn)它,太麻煩。而定義默認(rèn)方法,子類就都繼承了該方法,無需太多改動。那如果子類已經(jīng)有該同名方法了,Java會如何調(diào)用呢?答案是優(yōu)先調(diào)用子類方法。
public interface Function {
default String get() {
return "Function";
}
}
public class FuncitonImpl implements Function {
public static void main(String[] args) {
Function fun = new FuncitonImpl();
System.out.println(fun.get());
}
public String get() {
return "FuncitonImpl";
}
}
輸出結(jié)果:FuncitonImpl
-
高階函數(shù):方法參數(shù)為一個函數(shù)或者返回值為一個函數(shù)
方法重載時,如果一個方法參數(shù)為函數(shù)式接口,而另一個方法參數(shù)為其子類,那么調(diào)用方法時,會調(diào)用參數(shù)為子類的方法。
public interface IntegerBiFunciton extends BinaryOperator<Integer> {
}
public static void get(IntegerBiFunciton function ) {
System.out.println("IntegerBiFunciton function...");
}
public static void get(BinaryOperator<Integer> function ) {
System.out.println("BinaryOperator function...");
}
調(diào)用get方法時,輸出結(jié)果:IntegerBiFunciton function...