函数式编程
在从Java 8开始,引入了函数式编程接口与Lambda表达式,可以让我们简化某些匿名内部类,编写更少的代码来实现功能,使用Lambda表达式可以简化匿名内部类的书写,但Lambda表达式并不能取代所有的匿名内部类,只能用来取代函数接口的简写,例如在创建一个线程时,常见的写法是这样:
1 | new Thread(new Runnable(){// 接口名 |
上述代码给Tread类传递了一个匿名的Runnable对象,重载Runnable接口的run()方法来实现相应逻辑。使用lambda表达式可以简化为如下形式:
1 | new Thread( |
还是上面说的,使用Lambda的依据是必须有相应的函数式接口,函数式接口也是Java interface的一种,即内部只有一个抽象方法的接口,需要满足:
- 一个函数式接口只有一个抽象方法(single abstract method);
- Object类中的public abstract method不会被视为单一的抽象方法;
- 函数式接口可以有默认方法和静态方法;
- 函数式接口可以用@FunctionalInterface注解进行修饰。
这一点跟Java是强类型语言吻合,也就是不能在代码的任何地方写Lambda表达式。实际上Lambda的类型就是对应函数接口的类型。Lambda表达式另一个依据是类型推断机制,在上下文信息足够的情况下,编译器可以推断出参数表的类型,而不需要显式指名。
自定义函数接口很容易,只需要编写一个只有一个抽象方法的接口即可。
1 | @FunctionalInterface |
上面代码中的@FunctionalInterface是可选的,但加上该标注编译器会帮你检查接口是否符合函数接口规范。就像加入@Override标注会检查是否重载了函数一样。
有了上述接口定义,就可以写出类似如下的代码:
1 | ConsumerInterface<String> consumer = str -> System.out.println(str); |
Java内部也提供了一些可以直接使用的函数接口
1 | 1. Consumer<T> 消费型接口 |
这里要解释下什么是函数式编程
实际上,函数式编程没有一个严格的官方定义。严格上来讲,函数式编程中的“函数”,并不是指我们编程语言中的“函数”概念,而是指数学“函数”或者“表达式”(例如:y=f(x))。不过,在编程实现的时候,对于数学“函数”或“表达式”,我们一般习惯性地将它们设计成函数。所以,如果不深究的话,函数式编程中的“函数”也可以理解为编程语言中的“函数”。
每个编程范式都有自己独特的地方,这就是它们会被抽象出来作为一种范式的原因。面向对象编程最大的特点是:以类、对象作为组织代码的单元以及它的四大特性。面向过程编程最大的特点是:以函数作为组织代码的单元,数据与方法相分离。那函数式编程最独特的地方又在哪里呢?实际上,函数式编程最独特的地方在于它的编程思想。函数式编程认为程序可以用一系列数学函数或表达式的组合来表示。函数式编程是程序面向数学的更底层的抽象,将计算过程描述为表达式。不过,真的可以把任何程序都表示成一组数学表达式吗?
理论上讲是可以的。但是,并不是所有的程序都适合这么做。函数式编程有它自己适合的应用场景,比如科学计算、数据处理、统计分析等。在这些领域,程序往往比较容易用数学表达式来表示,比起非函数式编程,实现同样的功能,函数式编程可以用很少的代码就能搞定。但是,对于强业务相关的大型业务系统开发来说,费劲吧啦地将它抽象成数学表达式,硬要用函数式编程来实现,显然是自讨苦吃。相反,在这种应用场景下,面向对象编程更加合适,写出来的代码更加可读、可维护。
再具体到编程实现,函数式编程跟面向过程编程一样,也是以函数作为组织代码的单元。不过,它跟面向过程编程的区别在于,它的函数是无状态的。何为无状态?简单点讲就是,函数内部涉及的变量都是局部变量,不会像面向对象编程那样,共享类成员变量,也不会像面向过程编程那样,共享全局变量。函数的执行结果只与入参有关,跟其他任何外部变量无关。同样的入参,不管怎么执行,得到的结果都是一样的。这实际上就是数学函数或数学表达式的基本要求。
类似在断言中使用的就是将函数作为参数进行传递,函数本身并无状态
1 | lbsWrapper.next(this::advPredicate, advWrapper); |
- Title: 函数式编程
- Author: algorain
- Created at: 2022-03-09 10:51:30
- Updated at: 2023-05-14 22:10:20
- Link: http://www.rain1024.com/2022/03/09/函数式编程/
- License: This work is licensed under CC BY-NC-SA 4.0.