本文是「Java 8 函數式程式設計」第二章的讀書筆記。
Lambda引入的變化
Lambda表達式,是一種緊湊的、傳遞行為的方式,從程式設計思想上來講,就是代碼即資料。
過去的Java中,存在大量的匿名内部類的使用,會建立一個匿名内部類傳入調用的方法中。這種傳統的方式,會造成備援的、不易閱讀的代碼。
于是Lambda誕生了。Lambda的文法簡化了使用匿名内部類時的模闆代碼,讓程式員專注于編寫想要執行的行為,也讓代碼更加簡潔易讀。
Lambda表達式的形式
Runnable runable = () -> System.out.println("Hello Lambda");//1
runable = () -> {
System.out.print("Hello");
System.out.println(" Lambda");
};//2
ActionListener listener = event -> System.out.println("get event");//3
BinaryOperator add = (x, y) -> x + y;//4
BinaryOperator minux = (Long x, Long y) -> x - y;//5
常見的Lambda表達式有以上5種,每個Lambda表達式都可以分為三個部分:
參數部分:() event (x, y) (Long x, Long y)
将參數和表達式主體分開的符号:->
表達式主體
參數的形式
Lambda表達式可以看作是匿名内部類的簡寫形式,參數也就是使用匿名内部類時實作的方法的參數。
有的方法不需要參數,如Runnable的run方法,是以使用()代表參數部分。
有的方法隻需要一個參數且類型确定,如ActionListener.actionPerformed方法,可以直接使用參數,不需要指定類型,也不需要加括号。
有多個參數時,必須要加上括号,把參數擴起來
當聲明參數類型時,無論有多少個參數,都需要加括号
表達式主體的形式
表達式可以隻有一行代碼,也可以有多行代碼;有的表達式有傳回值,有的沒有。
隻有一行代碼的表達式不需要{}
如果有傳回值,不用寫return,表達式會把這行代碼的傳回值作為傳回值
如果使用了{},則需要顯式的寫出return
有多行代碼的表達式必須使用{}
如果有傳回值,需要顯式的寫return
引用值,而不是變量
匿名内部類中,如果想要引用其所在方法中的變量,需要将其聲明為final。這意味着你實際引用的是一個值,而不是變量。
在Java 8中,雖然可以引用非final的變量,但這個變量必須是既成事實上的final,如果對變量進行修改,将無法通過編譯。這意味着Lambda表達式仍然是引用的一個值,而不是變量。
實際上可以通過使用數組來繞開編譯器,但是這樣做之前應該考慮一下你的代碼邏輯是否正确。
函數接口
隻有一個抽象方法的接口叫做函數接口。
JDK中最重要的函數接口:
Interface
Argument
Return
e.g.
Predicate
T
boolean
fliter
Consumer
T
void
forEach
Function
T
R
map
Supplier
None
T
factory function
UnaryOperator
T
T
modify String
BinaryOperator
(T, T)
T
add two instances
類型推斷
Java 8為新成員Lambda表達式提供了類型推斷的支援,在不需要聲明參數類型的Lambda表達式中表現的有為明顯。形如:
BinaryOperator add = (x, y) -> x + y;
的表達式得以通過編譯并正确執行,就是因為JVM通過泛型參數Integer推斷出了方法參數的類型。