說來挺慚愧的,JDK8已經出來這麼多年,在實際項目中卻不多真正使用Lambda表達式。其實工做中的項目很早就從開發、測試、生產,全面使用JDK8+Tomcat8了。html
因此看來是時候要從新認識下這個奇怪的東西。java
沒錯,當第一次看到Lambda表達式時,我就認爲這是個奇怪的東西,->
寫法讓我感受這是在寫其它語言,說好的一切皆對象呢?oracle
這是Lambda表達式的基本語法:app
(Type1 param1, Type2 param2, ..., TypeN paramN) -> { statment1; statment2; //...... return statmentM; }
參數列表是一個逗號分隔的形式參數列表,這些參數與功能接口中單一方法的形式參數相對應。指定參數類型是可選項;若是未指定參數類型,將從上下文推斷。參數列表必須用括號括起來,但當指定的單一參數不帶參數類型時除外;指定單一形式參數時能夠不帶括號。若是功能接口方法不指定任何形式參數,則必須指定空括號。測試
語句塊必須包含在大括號內,除非語句塊是一個方法調用語句。ui
對於無參無返回值,能夠有以下寫法:this
public interface TestIntf { public void sayHello(); } // -> 前的一對小括號和後面的一對大括號都不能去掉。 TestIntf intf = () -> {System.out.println("HelloWorld!!!");}; intf.sayHello();
對於有參有返回值,能夠有以下寫法:code
public interface TestIntf { public String sayHello(String word); } // 完整寫法 TestIntf intf = (String word) -> {return "Hello " + word;}; // 參數word的類型能夠推斷時,能夠去掉類型定義: TestIntf intf = (word) -> {return "Hello " + word;}; // 甚至當參數只有一個時,能夠去掉左邊的小括號: TestIntf intf = word -> {return "Hello " + word;}; // 右側的方法體只有一個表達式時,能夠去掉大括號,甚至連return均可以不要: TestIntf intf = word -> "Hello " + word;
Lambda表達式內部能夠訪問外部的變量,但須要注意:htm
局部變量不管是在Lambda表達式主體中聲明,仍是在封閉做用域中聲明,使用以前都必須先初始化。如:對象
interface TestIntf { public String sayHello(String word); } public class App { public static void main(String[] args) { String str; TestIntf intf = (String word) -> { System.out.println(str); // 編譯失敗,提示str變量未被初始化。 return "Hello " + word; }; } }
Lambda表達式不會定義新的做用域;Lambda表達式的做用域與封閉做用域相同。如:
interface TestIntf { public String sayHello(String word); } public class App { public static void main(String[] args) { String str = "word"; TestIntf intf = (String word) -> { String str = ""; // 編譯失敗,提示str變量重複定義了。 return "Hello " + word; }; } }
並且也不能修改外部變量:
interface TestIntf { public String sayHello(String word); } public class App { public static void main(String[] args) { String str = "word"; TestIntf intf = (String word) -> { str = "word!!!"; // 編譯報錯:Local variable str defined in an enclosing scope must be final or effectively final return "Hello " + word; }; } }
固然,引用變量是能夠經過內部方法達到數據修改的。
interface TestIntf { public String sayHello(StringBuilder word); } public class App { public static void main(String[] args) { StringBuilder str = new StringBuilder("word"); TestIntf intf = (StringBuilder word) -> { word.append("!!!"); return "Hello " + word; }; System.out.println(intf.sayHello(str)); // Hello word!!! System.out.println(str); // word!!! } }
在Lambda表達式中this引用的不是Lambda表達式對象,而是聲明它的外部對象:
interface TestIntf { public String sayHello(); } public class App { public void test() { TestIntf intf = () -> "Hello " + this.getClass().getSimpleName(); System.out.println(intf.sayHello()); } public static void main(String[] args) { App app = new App(); app.test(); // Hello App } }