Dawn's Blogs

分享技术 记录成长

0%

Java高级 (11) lambda表达式

lambda 表达式

Lambda 是一个匿名函数,使用它可以写出更简洁、更灵活的代码。Lambda 表达式的本质:函数式接口的实现

在 Java 8 中引入了新的操作符 ->,称为 lambda 操作符或者箭头操作符。将 lambda 分为两个部分:

  • 左侧:指定了 Lambda 表达式需要的参数列表
  • 右侧:指定了 Lambda ,是抽象方法的实现逻辑。

lambda 表达式中参数数据类型可以省略,因为可由编译器推断得出,称为类型推断

应用举例:

lambda 表达式可以从匿名类转换为 lambda 表达式。

匿名类:

1
2
3
4
5
6
Runnable r = new Runnable() {
@Override
public void run() {
System.out.println("hello world");
}
};

lambda 表达式:

1
Runnable r = () -> System.out.println("hello world");

函数式接口

只包含一个抽象方法的接口,称为函数式接口。可以通过 Lambda 表达式来创建该接口的对象。

可以在一个接口上使用 @FunctionalInterface 注解,这样做可以检查它是否是一个函数式接口。同时 javadoc 也会包含一条声明,说明这个接口是一个函数式接口。

在 Java 中,Lambda 表达式是对象,而不是函数。Lambda 表达式就是一个函数式接口的实例

作为参数

Lambda 表达式可以作为参数传递,为了将 Lambda 表达式作为参数传递,接收 Lambda 表达式的参数类型必须是与该 Lambda 表达式兼容的函数式接口的类型。如:

定义函数式接口:

1
2
3
4
@FunctionalInterface
public interface MyFunc<T> {
public T getValue(T t);
}

定义函数:

1
2
3
public String f(MyFunc<String> mf, String s) {
return mf.getValue(s);
}

Lambda 表达式作为函数参数:

1
String ret = f(str -> str.toUpperCase(), "abcde")

内置函数型接口

在 java.util.function 包下定义了丰富的函数式接口。

四大核心函数式接口:

image-20230207100650390

其他接口:

image-20230207100836806

方法引用构造器引用

方法引用

Lambda 表达式中的操作已经有实现的方法了,就可以使用方法引用。方法引用就是 Lambda 表达式,也就是函数式接口的一个实例,通过方法的名字来指向一个方法。格式:使用操作符 :: 将类(对象)与方法名字分隔。

要求:实现接口的抽象方法的参数列表和返回值类型,必须与方法引用的方法的参数列表和返回值类型保持一致。

有三种使用情景:

  • 对象::实例方法名。
  • 类::静态方法名。
  • 类::实例方法名(this 看作是第一个参数)

如:

1
2
3
4
Comparator<Integer> com1 = (x, y) -> Integer.compare(x, y);

// 等同于
Comparator<Integer> com2 = Integer::compare;

构造器引用

也可以使用构造器引用,把构造器引用赋值给函数型接口。格式:ClassName::new

要求:构造器参数列表要与接口中抽象方法的参数列表一致,且方法的返回值即为构造器对应类的对象。

如:

1
2
3
4
Function<Integer, MyClass> fun1 = (n) -> new MyClass(n);

// 等同于
Function<Integer, MyClass> fun2 = MyClass::new;

数组构造器引用:

1
2
3
4
Function<Integer, Integer[]> fun1 = (n) -> new Integer[n];

// 等同于
Function<Integer, Integer[]> fun1 = Integer[]::new;