在这篇文章中,我们将了解到在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
复制代码
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}
复制代码
为了接收传递过来的函数引用,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下如何进行函数式编程,以及如何定义和使用一个函数式接口。