1
Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。
Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
使用 Lambda 表达式可以使代码变的更加简洁紧凑。
语法
lambda 表达式的语法格式如下:
(parameters) -> expression
或
(parameters) ->{ statements; }
以下是lambda表达式的重要特征:
可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定表达式返回了一个数值。
Lambda 表达式实例
Lambda 表达式的简单例子:(和javascript的箭头函数语法相仿,都是无参数一个(),1个参数可省略(),多个参数需要())
// 1. 不需要参数,返回值为 5
() -> 5
// 2. 接收一个参数(数字类型),返回其2倍的值
x -> 2 * x
// 3. 接受2个参数(数字),并返回他们的差值
(x, y) -> x – y
// 4. 接收2个int型整数,返回他们的和
(int x, int y) -> x + y
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s)
public class Lam { public static void main(String[] args) { //类型声明(Integer::sum,静态方法引用) // public static int sum(int a, int b) { // return a + b; // } // XiaoXuMath addition= Integer::sum; XiaoXuMath addition= (int a,int b)->a+b; //不用类型声明 XiaoXuMath subtraction=(a,b)->a-b; //大括号中的返回语句 XiaoXuMath mul=(int a,int b)->{return a*b;}; //没有大括号及返回语句 XiaoXuMath div=(int a,int b)->a/b; System.out.println(addition.oper(12,54)); Lam h=new Lam(); System.out.println("12+54:"+h.getValue(12,54,addition)); System.out.println("7-9:"+h.getValue(7,9,subtraction)); System.out.println("5*4:"+h.getValue(5,4,mul)); System.out.println("28/7:"+h.getValue(28,7,div)); } interface XiaoXuMath{ int oper(int a,int b); } private int getValue(int x,int y,XiaoXuMath m){ return m.oper(x,y); } }
66 12+54:66 7-9:-2 5*4:20 28/7:4
使用 Lambda 表达式需要注意以下两点:
Lambda 表达式主要用来定义行内执行的方法类型接口,例如,一个简单方法接口。在上面例子中,我们使用各种类型的Lambda表达式来定义XiaoXuMath接口的方法。
Lambda 表达式免去了使用匿名方法的麻烦,并且给予Java简单但是强大的函数化的编程能力。
变量作用域
lambda 表达式只能引用标记了 final 的外层局部变量,这就是说不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误。
public class UseLam { final static String salutation="Hello?"; static String test="我是test"; public static void main(String[] args) { Greet g=msg -> System.out.println(salutation+msg); g.sayMessage("xiaoxu!"); WantToTest w1=e->e+"nihao"; System.out.println(w1.test1(test)); System.out.println(test); } interface Greet{ void sayMessage(String msg); } interface WantToTest{ String test1(String x1); // void test2(String x2); } }
Hello?xiaoxu! 我是testnihao 我是test
也可以直接在 lambda 表达式中访问外层的局部变量:
public class UseLam{ public static void main(String[] args) { int num=1; Converter<Integer,String> c=i -> System.out.println("你好:"+String.valueOf(i+num)); c.convert(45); System.out.println(c); System.out.println(c.getClass()); } @FunctionalInterface public interface Converter<T1,T2>{ void convert(int i); } }
你好:46 com.xiaoxu.boot.learn.UseLam$$Lambda$1/1198108795@6f539caf class com.xiaoxu.boot.learn.UseLam$$Lambda$1/1198108795
lambda 表达式的局部变量可以不用声明为 final,但是必须不可被后面的代码修改(即隐性的具有 final 的语义)
在 Lambda 表达式当中不允许声明一个与局部变量同名的参数或者局部变量。
public static void main(String[] args) { String x=""; Comparator<String> c=(f,s)->Integer.compare(f.length(),s.length()); String a="1"; String b="78"; System.out.println(c.compare(a, b)); }
-1
Comparator是函数式接口,所以可以实例化赋值lambda、方法引用、构造方法引用
但是修改成功局部变量同名的参数后,会报错: