说来挺惭愧的,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 } }