Java函数式编程:Lambda表达式和函数式接口

版权声明:本文为博主原创文章,未经博主允许不得用于任何商业用途,转载请注明出处。 https://blog.csdn.net/fyyyr/article/details/86289428

Lambda表达式

Java的Lambda表达式形式为:

(params) -> { statements };

其中:

  1. 若params只有1个,可以省略():param -> { statements };
  2. 若params为0个,用()表示无参数:() -> { statements };
  3. 若代码为一行,则可省略{},无论该行代码是否为表达式:(params) -> expression;(params) -> statement;

函数式接口

Lambda表达式本质上是一个对象。而对象就必然有其对应的类型,就像一个字符串其类型为String一样。
当一个函数,其参数需要传入一个Lambda表达式时,函数的参数就需要明确定义该Lambda表达式的类型。
实际上,Java的Lambda表达式都是归属于某个具体已定义的类型的。根据Lambda表达式的参数与返回值数量和类型,Java定义了一组interface来接收Lambda表达式,称之为函数式接口

函数式接口有以下条件:

  1. 是一个interface。
  2. 有且仅有一个抽象方法。

另外:

  • interface默认继承Java.lang.Object,故Object的抽象方法不包含在内。
  • 可以使用@FunctionalInterface注解来标记函数式接口,有助于编译器进行检查。但@FunctionalInterface注解并非必须,只要满足条件,即使没有@FunctionalInterface注解编译器也会将接口识别为函数式接口。

例如:

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

Java8以后,Runnable接口多了@FunctionalInterface注解。这表示Runnable接口成为函数式接口了,可以接收Lambda表达式。
而实际上,由于Runnable接口有且仅有一个抽象方法,满足函数式接口的条件,所以即使不加@FunctionalInterface注解也依然会被识别为函数式接口。
所以可以自定义函数式接口:

@FunctionalInterface
public interface MyInterface {
    // 定义唯一的抽象方法
    void doWork();
    // toString()属于Object,不包含
    String toString();
}

使用:

MyInterface myInterface = () -> System.out.println("do work");

或将其作为参数类型:

class MyClass {
  public void doMyWork(MyInterface myInterface) {
    myInterface.doWork();
  }
}

MyClass myClass = new MyClass();
myClass.doMyWork(() -> System.out.println("do work"));

前面提到的Runnable接口同理。
除了Runnable接口,Java8还提供了一组函数式接口:

接口 参数 返回类型 描述
Predicate T boolean 判断一个对象是否符合条件。常用于对象过滤。
Function<T, R> T R 将一个对象转换为另一个对象。
Supplier None T 提供一个对象。生产者-消费者中的生产者。
Consumer T void 消费一个对象。生产者-消费者中的消费者。无返回值。
UnaryOperator T T 接收对象并返回同类型的对象。
BinaryOperator (T, T) T 接收两个对象,并返回一个原对象。这三个对象的类型都相同。

其中:

  1. Supplier是唯一无参数的函数。其他函数都必须传入参数。
  2. Consumer是唯一无返回的函数。其他函数都会返回一个对象。

Runnable接口则是无参数,无返回值的。

猜你喜欢

转载自blog.csdn.net/fyyyr/article/details/86289428