超越Java8

聲明式編程

”如何做”風格的編程非常適合經典的面向對象編程,有些時候我們也稱之爲“命令式”編程,因爲它的特點是它的指令和計算機底層的詞彙非常相近,比如賦值,條件分支以及循環,就像下面的這段代碼:

Transaction mostExpensive = transactions.get(0);
if(mostExpensive == null){
	throw new IllegalArgumentException("Empty list of transaction");
}
for(Transaction t: transactions.subList(1,transactions.size())){
	if(t.getValue() > mostExpensive.getValue()){
		mostExpensive = t;
	}
}

另一種方式則更加關注要做什麼,例如如下:

Optional<Transaction> mostExpensive = transactions.stream().max(comparing(Transaction::getValue));

這個查詢把最終如何實現的細節留給了函數庫。我們把這種思想稱之爲內部迭代。它的巨大優勢在於你的查詢語句現在讀起來就像是問題描述,由於採用了這種方式,我們馬上就能理解它的功能,比理解一系列的命令要簡潔得多。

採用這種“要做什麼”風格的編程通常稱爲聲明式編程。它帶來的好處非常明顯,用這種方式編寫的代碼更加接近問題陳述了。

函數式編程

編程實戰中,你是無法用Java語言以純粹的函數式來完成一個程序的。比如,Java的I/0模型就包含了帶副作用的方法。純粹的函數式需要使用同樣的參數調用數學函數,它所返回的結果一定是相同的。
我們的準則是,被稱爲“函數式”的函數或方法都只能修改本地變量。除此之外,它引用的對象都應該是不可修改的對象。通過這種規定,我們期望所有的字段都爲final類型,所有的引用類型都指向不可變對象。
如果你的共享變量在某一刻是改變的,那麼這個變量在多線程程序中就是有風險的。你用加鎖的方式來對方法的方法體進行封裝,掩蓋這一問題,但是這樣做了之後,就喪失了多核處理器併發執行兩個方法調用的能力。
作爲函數式地程序,你的函數或方法調用的庫函數如果有副作用,你必須設法隱藏它們的非函數式行爲,否則就不能調用這些方法。

引用透明性

”沒有可感知的副作用“(不改變對調用者可見的變量、不進行I/O、不拋出異常)的這些限制都隱含着引用透明性。如果一個函數只要傳遞同樣的參數值,總是返回同樣的結果,那這個函數就是引用透明的。
換句話說,函數無論在何處、何時調用,如果使用同樣的輸入總能持續地得到相同的結果,就具備了函數式的特徵。所以,Random.nextInt不是函數式的方法,而final int 類型的變量相加總能得到相同的結果。
引用透明性是理解程序的一個重要屬性。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章