Lambda表达式

1. Lambda表达式

1.1 设计

  • 面向过程语言
  • 面向对象语言
  • 函数式程序语言(传递方法/代码块)-- Java8开始,推出Lambda表达式实现

1.2 形式

  • 参数,箭头,一个表达式
  • 参数,箭头,
  • 无参数,仅保留括号,箭头,表达式
  • 一个参数,可省略括号,箭头,表达式
  • 如果有返回值,类型通过上下文推断,无需声明,只在某几个分支有返回值是不合法的

1.3 特点

  • 类似与匿名方法
  • 参数,箭头,表达式语句
  • 可以忽略写参数类型,上下文推断
  • 坚决不声明返回值类型,上下文推断
  • 没有public/protected/private/static/final等修饰符
  • 单句表达式,将直接返回值,不用大括号
  • 带return语句,算多句,必须用大括号

2. 函数式接口

2.1 定义

  • 是一个接口,符合Java接口的定义
  • 只包含一个抽象方法的接口
  • 可以包括其他的default方法、static方法、private方法
  • 由于只有一个未实现的方法,所以lambda表达式可以自动填上这个尚未实现的方法
  • 采用lambda表达式,可以自动创建出一个(伪)嵌套类的对象(没有实际的嵌套类class文件产生),然后使用,比真正嵌套类更加轻量,更加简洁高效

2.2 系统自带的函数式接口

2.3 自定义函数式接口

建议使用@FunctionalInterface注解,用于编译器检查

3. 方法引用

Lambda表达式支持传递现有的类库函数,实现接口的抽象方法的参数列表和返回值类型,必须与方法引用的方法的参数列表和返回值类型保持一致

3.1 Class::staticMethod,如Math.abs方法

  • 等价于提供方法参数的Lambda表达式
  • Math::abs等价与x->Math.abs(x)

3.2 Class::instanceMethod,如String::compareToIgnoreCase方法

  • 第一个参数将变成方法的执行体
  • String::compareToIgnoreCase等价于(x,y)->x.compareToIgnoreCase(y)

3.3 Object::instanceMethod,如System.out.println方法

  • 等价于提供方法参数的Lambda表达式

  • System.out::println等价于x->System.out.println(x)

  • 支持this::instanceMethod和super::instanceMethod

3.4 Class::new ,调用某类构造函数,创造一个对象

Supplier<Person> s = Person::new;
Person p = s.get();

3.5 Class[]::new,支持数组对象创建

IntFunction<int[]> intArray=int[]::new;
int[] nums=intArray.apply(10);

Function<Integer,Person[]> personArray=Persion[]::new;
Person[] persons=personArray.apply(5);

4. Lambda表达式应用

4.1 类型信息

  • 类似于匿名方法,一个没有名字的方法
  • 被赋值后,可以看作是一个函数式接口的实例(对象)
  • lambda表达式没有存储目标类型的信息

4.2 重载调用

  • 重载调用,依据重载的规则和类型参数推理

4.3 变量遮蔽

  • lambda表达式和匿名内部类/局部内部类一样,可以捕获变量,即访问外部嵌套块的变量,但是变量要求是final或者是effectively final(不是final,但实际未改变值)
  • lambda表达式没有变量遮蔽问题,因为它的内容和嵌套块有着相同的作用域,在表达式中,不可以声明与(外部嵌套块)局部变量相同名的参数或者局部变量

4.4 this指代

  • lambda表达式中的this,就是创建这个表达式的方法的this参数,可以对应的函数式接口中的this无关

4.5 Lambda表达式应用

  • 填充接口的一个抽象方法

  • 接口支持有默认方法/静态方法/私有方法

  • lambda表达式优先级比嵌套类高

    • 短小精干,本身可以自描述
    • 无法创建命名实例,无法获取自身的引用(this)
  • 方法引用比自定义lambdai表达式的优先级高

    • 系统自带的方法引用更简洁高效
    • 对于复杂的lambda表达式,采用方法引用比内嵌lambda表达式更清晰,更容易维护
  • 建议使用标准的函数式接口,更容易学习,提高互操作性

posted @ 2022-05-13 00:42  hunter-w  阅读(37)  评论(0编辑  收藏  举报