最初的Lambda語法飽受詬病,但實際上,問題的嚴重性遠不止純粹的語法那么簡單(畢竟,語法只不過是個外表而已)。其中一個主要的問題是Java并沒有對函數(shù)類型提供直接的支持,這給Java類型系統(tǒng)帶來了一些問題(函數(shù)數(shù)組可能引起異常泄漏)。無論能否克服這些問題(或者說在給定的JDK 7延期發(fā)布的時間內),Lambda都不會再涉及函數(shù)類型了。
我們可以采用適配的方式簡化內部類的編寫過程。這些類叫做SAM(即Single Abstract Method)類。它代表了Java語言中抽象類與接口的一個重要子集,僅包含一個抽象方法。比如說,Runnable接口的run()方法、Comparator接口的compare()方法等(只包含一個抽象方法的抽象類也是可以的,比如Eclipse的org.eclipse.core.runtime.jobs.Job)。
目前進行中的規(guī)范表明下面兩種表達方式是等價的:
Collections.sort(list,new Comparator() {
public int compare(Object o1, Object o2) {
return(o1.toString().length() - o2.toString().length());
}
}
// is the same as
Collections.sort(list,
{ Object o1, Object o2 -> o1.toString().length() - o2.toString().length() }
);
不得不說的是,Lambda語法依然處于提案階段,未來可能會發(fā)生變化,但基本想法是在Lambda項目的幫助下,我們可以更加簡潔的方式編寫內部類,從而拋棄現(xiàn)在所用的匿名類方式。另外,Lambda會保持與內部類一樣的表現(xiàn)力,可以從局部堆中獲取狀態(tài)(但堆是否要保持可變的狀態(tài)依然是人們爭論的熱門話題)。然而,語言本身的一些變化(比如說可以高效獲取final變量)以及類型與方法/異常推斷的能力使得Lambda要比相應的匿名類更加簡潔。
之所以采取這種方式,一個原因就是可以不必修改現(xiàn)有的類(主要是 java.util包中的集合類)。假如使用了函數(shù)類型方式,那么就必須得修改集合類以適應Lambda,或者是在JDK 7中放棄對Lambda的支持。其他程序庫可能比較靈活,但整個Java類庫并非這么容易修改,這也解釋了為什么要采取其他方式。
還可以使用方法引用來代替SAMbda。如下代碼所示:
public class Comparisons {
public static int compareLength(Object o1, Object o2) {
return(o1.toString().length() - o2.toString().length());
}
public static int compareHash(Object o1, Object o2) {
return(o1.hashCode() - o2.hashCode());
}
}
// examples
Collections.sort(list,#Comparisons.compareLength);
Collections.sort(list,#Comparisons.compareHash);
#代表方法句柄,類似于java.lang.reflect.Method。然而,與Method不同的是,他們是在編譯期(而非運行期)確定的,JVM的JIT可以自動內聯(lián)方法引用。這么做還具有其他優(yōu)化效果,比如說針對給定的SAM類型,可以單獨創(chuàng)建一個類表示代理的方法句柄而不必在使用時創(chuàng)建新的匿名類。
最后,還是存在一些有爭議的問題。目前規(guī)范的最初草案禁止使用break和continue,但后來澄清說這么做的目的是為了防止跳出SAMBda而進入到封閉的范圍內。另外一個主要的變化是return變成隱式的了,不允許在Lambda內部使用;但替代的關鍵字yield(不要與Thread.yield()混為一談)與內部類中的return具有相同的語義。表面上來看,這么做可以實現(xiàn)在方法調用后,使用Lambda觸發(fā)方法中的return的效果(即所謂的“long return”)。未來在語法上也會有一些變化,可以在Lambda中使用return,這需要使用新的關鍵字(或是關鍵字組合,比如long return)。其他相似之處還有使用this引用封閉的SAM實例,使用Outer.this引用封閉類的實例。
雖說使用Lambda替換SAM這個決定不如項目最初的提案那樣雄心勃勃,但還是有不少優(yōu)勢的:實現(xiàn)簡單、無需修改現(xiàn)有的集合類、能夠很快派上用場(不管使用何種方式,只要增加函數(shù)類型就需要修改集合類)。未來,還可以使用相同的Lambda語法創(chuàng)建函數(shù)引用,但其目標是今后發(fā)布的JDK版本。