Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。 Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。 使用 Lambda 表达式可以使代码变的更加简洁紧凑。
语法 1 2 3 (parameters ) -> expression (parameters ) -> { statements; }
重要特性 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。
示例程序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 public class LambdaRelevant { public static void main (String[] args) { MathOperation addition= Integer::sum; MathOperation subtraction=(int a,int b)->a-b; MathOperation multiplication=(a,b)->{return a*b;}; MathOperation division=(a,b)->a/b; String n="evan" ; GreetingService greetingService = msg -> { System.out.println(msg+" " +n);}; LambdaRelevant lambdaRelevant = new LambdaRelevant(); System.out.println("1+1=" +lambdaRelevant.operation(1 ,1 ,addition)); System.out.println("2-1=" +lambdaRelevant.operation(2 ,1 ,subtraction)); System.out.println("2*1=" +lambdaRelevant.operation(2 ,1 ,multiplication)); System.out.println("2/2=" +lambdaRelevant.operation(2 ,2 ,division)); greetingService.message("Hello" ); } interface MathOperation { int operation (int a,int b) ; } @FunctionalInterface interface GreetingService { void message (String msg) ; public boolean equals (Object var ) ; public default void defaultMethod () { System.out.println("this is default method" ); } public static void staticMethod () { System.out.println("this is static method" ); } } interface TalkSerivce { void Whisper (String msg) ; void Loud (String msg) ; } private int operation (int a,int b,MathOperation mathOperation) { return mathOperation.operation(a,b); } }
方法引用 方法引用是Java8 的新特性。 我们知道,使用Lambda表达式可以极大地简化我们的代码,但有时候Lambda体中的功能已经有现成的方法实现了,这时我们可以直接使用方法引用,而不是重复地去实现该功能。
方法引用可以理解为Lambda表达式的另一种表现形式。
方法引用引用的方法的参数列表和返回值类型,必须和函数式接口中抽象方法的参数列表和返回值类型保持一致。
构造器引用:Class::new
静态方法引用:Class::static_method
特定类的任意对象的方法引用:Class::method
特定对象的方法引用:instance::method
总结
函数式接口(Functional Interface),在这个接口里面只能有一个抽象方法,这种类型的接口也称为SAM接口,即Single Abstract Method interfaces。
关于@FunctionalInterface注解,Java 8为函数式接口引入了一个新注解@FunctionalInterface,主要用于编译级错误检查,加上该注解,当你写的接口不符合函数式接口定义的时候,编译器会报错。
该注解只能标记在”有且仅有一个抽象方法”的接口上。
JDK8接口中的静态方法和默认方法,都不算是抽象方法。
接口默认继承java.lang.Object,所以如果接口显示声明覆盖了Object中方法,那么 也不算抽象方法。 PS:该注解不是必须的,如果一个接口符合”函数式接口”定义,那么加不加该注解都没有影响。加上该注解能够更好地让编译器进行检查。如果编写的不是函数式接口,但是加上了@FunctionInterface,那么编译器会报错。
lambda 表达式只能引用标记了 final 的外层局部变量(final关键字可以省略),这就是说不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误。(lambda 表达式的局部变量可以不用声明为 final,但是必须不可被后面的代码修改(即隐性的具有 final 的语义))
在 Lambda 表达式当中不允许声明一个与局部变量同名的参数或者局部变量。
待做
了解什么是JDK8接口中的默认方法。
了解forEach。
动手用代码尝试一下方法引用。