转载

一起来学Java8(一)——函数式编程

所谓的函数式编程就是把函数名字当做值进行传递,然后接收方拿到这个函数名进行调用。

首先来看下JavaScript如何进行函数调用

 1var Person = {
 2    sayHello: function(name) {
 3        alert('hello ' + name);
 4    }
 5};
 6
 7function work(fn) {
 8    fn('Jim');
 9}
10
11work(Person.sayHello); // hello Jim
复制代码

在这个例子中,sayHello函数被当做一个参数传递到另一个work函数当中,然后work调用给定的函数。

Java8中的函数式编程

在Java中,充当函数的角色是类中方法,在本篇文章当中提到的函数泛指方法。

接下来看下Java8中一个简单的函数式编程例子:

 1import java.util.function.Consumer;
 2
 3class Person {
 4    public static void sayHello(String name) {
 5        System.out.println("hello " + name);
 6    }
 7}
 8
 9public class TestPerson {
10
11    public static void main(String[] args) {
12        work(Person::sayHello); // hello Jim
13    }
14
15    public static void work(Consumer<String> consumer) {
16        consumer.accept("Jim");
17    }
18}
复制代码

从这个例子中可以看到,Java8传递函数的方式跟JavaScript不一样,在Java8当中传递函数的方式是:方法引用::方法名称,如:String.valueOf,String.toString。接收参数Consumer可以先不用去了解,后面会讲到。

为了接收传递过来的函数引用,Java设计者提出了一个函数式接口的概念

函数式接口

函数式接口定义:一个接口里面只有一个抽象方法。

如下面几个接口都是函数式接口:

  • Consumer

  • Supplier

  • Runnable

  • Callable

查看Runnable类的源码可以发现,在类上方定义了一个@FunctionalInterface注解

1@FunctionalInterface
2public interface Runnable {
3    public abstract void run();
4}
复制代码
  • @FunctionalInterface注解的作用:

当做一个标记使用,标记当前接口是一个函数式接口,如果你的接口有多个抽象方法或没有抽象方法,那么会编译报错。它的作用有点类似于@override注解,有辅助作用,但不是必须的。如果你想设计一个函数式接口,那么最好把它加上。

 1// 编译不通过,必须要有一个抽象方法
 2@FunctionalInterface
 3public interface InterfaceA {
 4
 5}
 6
 7// 编译通过,只有一个抽象方法
 8@FunctionalInterface
 9public interface InterfaceB {
10    void run();
11}
12
13// 编译不通过,只能有一个抽象方法
14@FunctionalInterface
15public interface InterfaceC {
16    void run();
17
18    void run2();
19}
20
21// 编译通过,run2是默认方法,并不是抽象方法
22// 在这里只有一个run抽象方法
23@FunctionalInterface
24public interface InterfaceD {
25    void run();
26
27    default void run2() {};
28}
复制代码

在例子InterfaceD中涉及到了接口默认方法default void run2() {};,这里略过不讲,后续文章中会有提到。

我们可以实现一个自定义的函数式接口,替代Consumer

 1// 自定义函数式接口
 2@FunctionalInterface
 3public interface FunctionCaller<T> {
 4    void call(T t);
 5}
 6
 7public class TestPerson2 {
 8
 9    public static void main(String[] args) {
10        work(Person::sayHello);
11    }
12
13    public static void work(FunctionCaller<String> caller) {
14        caller.call("Jim");
15    }
16}
复制代码

小结

本篇主要讲解了在Java8下如何进行函数式编程,以及如何定义和使用一个函数式接口。

原文  https://juejin.im/post/5e7f21626fb9a03c46491f0b
正文到此结束
Loading...