Java Lambda 表达式

double

Java Lambda 表达式是 Java8 引入的一个新功能,可以说是模拟函数式编程的一个语法糖,类似于 Javascript 中的闭包,但又有些不同,主要目的是提供一个函数话的语法来简化我们的编码。

老式写法

如最常见的 Thread 类

Thread thread = new Thread(new Runnable() { @Override public void run() { // 相关代码 } });

这种回调模式在业务中非常常见,但是像上面这样的匿名内部类并不是一个好的选择,因为:

  • 语法沉淀
  • 匿名内部类中的this指针和变量容易产生误解
  • 无法捕获飞 final 局部变量
  • 非静态内部类默认持有外部类的引用,部分情况下会导致外部类无法被GC回收,导致内存泄漏

基于以上几点,Java8 为我们带来了 Lambda 表达式。

Lambda 基本语法

Lambda 的基本结构 (argument) -> body,有如下几种情况:

  • 参数类型可推导, 不需要指定类型, 如: (v) -> System.out.printIn(v)
  • 当只有一个参数且类型可推导时,不强制写 (), 如: v -> System.out.printIn(v)
  • 参数指定类型时,必须有括号, 如: (int v) -> System.out.printIn(v)
  • 参数可以为空, 如: () -> System.out.printIn(“hello”)
  • boby 需要用 {} 语句包含,当只有一条语句时可省略

常见的写法如下:

(a) -> a * a;
a -> a * a;
() -> System.out.printIn(“hello”)
(int a, String b) -> System.out.printIn(a + b)
(a, b) -> { retrun a - b }

函数式接口 FunctionalInterface

所谓函数式接口,当然首先是一个接口,然后就是这个接口有且只有一个抽象方法。这种类型的接口也称为SAM接口(Single Abstract Method Interface)

特点

  • 接口有且只有一个抽象方法
  • 允许定义静态方法
  • 允许定义默认方法
  • 允许java.lang.Object 中的 public 方法
  • 该注解不是必须的,如果一个接口符合 “函数式接口” 的定义,那不加不加该注解也没有影响,加上该注解能让编译器更好的进行检查,如果写的不是"函数式接口"但是加了 @FunctionalInterface,那么编译器会发生报错。

例子

正确的函数式接口

public interface TestInterface { // 抽象方法 public void sub(); // java.lang.Object 中的 public 方法 @Override public boolean equals(Object var1); // 默认方法 public default void defaultHandle() { System.out.println("233"); } // 静态方法 public static void staticMethod() { } }

错误的函数式接口,存在多个抽象方法

public interface TestInterface2 { void add(); void sub(); }

用法

使用 Lambda 表达式会帮我们自动实例化类。

第一步, 定义函数式接口TestInterface

public interface TestInterface { /** * lambda表达 * @param name */ void start(String name); /** * 默认方法 * @param name */ default void runHandle(String name) { start(name + "-->通过静态方法实现"); System.out.println("执行默认方法"); test(); } /** * 静态方法 */ static void test() { System.out.println("静态方法结束了"); } }

第二步,调用

public class Main { /** * 会自动实例化 */ private TestInterface testInterface = (val) -> System.out.println(val); public void foo() { testInterface.runHandle("fff"); } public static void main(String[] args) { Main main = new Main(); main.foo(); } }

方法引用

方法引用(Method Reference)的基础同样是函数式接口,可以直接作为函数式接口的实现,与 Lambda 表达式有相同的作用,同样依赖于类型推到,方法引用可以看作是只调用一个方法的 Lambda 表达式的简化。

方法引用的语法为:

  • 静态方法引用: Type::methodNam, 如: Person.say
  • 实例对象引用: instanceName::methodName, 如: person.say
  • 超类上的实例方法引用: super::methodName
  • 构造方法引用: Class::new
  • 数组构造方法引用: TypeName[]::new

Stream 对象

这是 Stream 不同于 io 中的 InputStream 和 OutputStream,是 java8 新加入的特性,位于 java.util.stream 包中。Stream 指的是一组支持串行并行聚合操作的元素,可以理解为集合或者迭代器的增强版,什么是聚合操作? 简单举例来说常见的有平均值、最大值、最小值、总和、排序、过滤等。

扩展阅读