Java 8 函数式编程(五)(Supplier 接口)

1,050 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第10天,点击查看活动详情

上一篇文章我们介绍了Predicate 接口,这篇文章我们来介绍一下Supplier 接口。

Supplier 接口

就像之前介绍的几个内置接口一样,我们通过接口的名字其实就大致可以看出这个接口的相关功能。Supplier 的意思是“供应厂商、供应者”,所以它也被称作为“供给型接口”。它的作用就是提供对象实例。

我们来看Supplier 接口的函数定义:

@FunctionalInterface
public interface Supplier<T> {

    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}

相比前几个接口来说,它的定义就显得十分简单了。它内部只有一个get 方法,没有其他接口的那些default 方法。

从这个方法我们也可以清晰地看出,不需要任何参数,却返回一个实例。

使用举例

我们先声明一个“学生类”:

class Student {
  String name;
  public Student() {
    this.name = "anonymity";
  }
  public Student(String name) {
    this.name = name;
  }
}

然后我们使用Supplier 接口来创建这个类的实例:

public static void main(String[] args) {

  Supplier<Student> supplier = Student::new;
  Student student = supplier.get();
  
  Supplier<Student> supplier1 =() -> new Student("xiaoming");
  Student student1 = supplier1.get();
}

以上代码也很简单,同时也很清晰、很实用。特别需要注意的是,上述例子中,每一次调用get 方法都会创建新的对象。

函数式接口复盘

其实我们可以简单记忆:函数式接口就是只有一个方法的接口,如在Java 8 之前已有的Runnable、Callable、Comparable 都称作函数式接口。

java 8 新加了一个专门用于标识函数式接口的注解@FunctionalInterface

在有了函数式接口之后,我们就可以将原本只能使用匿名函数的代码进行简化,如:

Thread thread = new Thread(new Runnable() {
  @Override
  public void run() {
    System.out.println("hello world");
  }
});

在Java 8 中只需要一行就可以解决:

Thread thread = new Thread(() -> System.out.println("hello world"));

其实我们很多代码都可以发现使用了lambda 表达式的语法。

关于lambda的格式为()->{}->为分隔符,我们可以发现:其左半部分为参数列表(参数在小括号中,没有参数的时候,小括号为空);右半部分为语句代码(在大括号内部,如果只有一行代码,那么大括号可以省略)。

而上述匿名类之所以能够被替换成Java 8 中的语法,主要由于Runnable 是函数式接口,使用lambda 表达式时会自动寻找并匹配合适的函数式接口。其匹配规则主要就看函数的入参和出参的类型、个数是否一致。

在上述Runnable接口中,它的只有一个方法,同时这个方法没有入参,出参为void,与 () -> System.out.println("hello world") 的参数及返回值表现一致。

总结

这篇文章我们讲了Supplier 接口的使用,同时复盘了函数式接口的相关知识点,相信我们对函数式接口的使用已经初步有了“拨开云雾见月明”的感觉了。