承接上文:Java函数式编程:一、函数式接口 , lambda表达式和方法引用这次来聊聊函数式编程中其他的几个比较重要的概念和技术,从而使得我们能更深刻的掌握Java中的函数式编程 。本篇博客主要聊聊以下几个问题
- 高阶函数
- 闭包概念
- 函数组合处理函数的使用
- 柯里化以及部分求值下面开始:
定义:高阶函数是一个能接受函数作为参数或能够把函数作为返回值的函数 。
public interface Function{String str(String s);}public class Procudure{// 下面就是一个标准的高阶函数public Function(String s){return s -> s.upperCase();}}
这里有两点:- 我们可以通过继承
java.util.function
中的接口,或是自定义一个函数式接口来为专门的接口创建别名 - 有了lambda表达式,很明显,我们很轻松就能创建并返回一个函数
public class test {public static Function<String, String> transform(Function<String, String> f){return f.andThen(String::toUpperCase);}public static void main(String[] args) {Function<String, String> transform = test2.transform(str -> {return str.substring(0, 2);});String s = transform.apply("abcdefg");System.out.println(s);}}
可以看到,这里我们通过andThen()
这个Function
接口的通用方法,连接了前后两个方法 , 并且使得无论我们输入了什么,都会将该字符串转化为全大写,后面我们输入了一个截取前两个字符作为返回值的方法,但很明显,这里可以有更多的选择,并且我们实际上也可以通过方法引用来引用某些定义好的函数,非常灵活 。2、闭包什么是闭包?
考虑一个lambda表达式 , 它使用了其函数作用域之外的变量 。当返回该函数时会发生什么呢?也即,当我们通过调用lambda表达式产生的匿名方法引用这些外部变量会发生什么呢?
如果一门语言能够解决这个问题,我们就认为该语言是支持闭包的,或者也可以说它支持词法作用域 。
这里还涉及到一个术语:变量捕获
【Java函数式编程:二、高阶函数,闭包,函数组合以及柯里化】上面听起来是不是不明白,没关系,给个例子:
public class Example{IntSupplier plus(int x){int y = 1;return () -> x + y;}}
考虑这个类和其中的方法plus(int x)
,你会不会发现有一些问题 。因为我们的
plus(int x)
方法返回的是一个函数 , 这里假设返回的函数是f(int x)
,也就是说,f(int x)
返回时,plus(int x)
已经执行结束,所以其中的变量int y = 1;
已经脱离了作用域,那么等到我们获取了f(int x)
的对象再调用到f(int x)
方法时,这个y
要怎么办呢?你会发现 , 上面的这个方法是可以被编译执行成功的,但是下面的这个就不行:
public class Example{IntSupplier plus(int x){int y = 1;return () -> x + (++y);}}
为什么呢?编译器提示:
推荐阅读
- 夯实Java基础,一篇文章全解析线程问题
- 四 Java多线程-ThreadPool线程池-2
- <一>从指令角度了解函数堆栈调用过程
- 生成器函数 javascript异步编程之generator与asnyc/await语法糖
- Java Timer使用介绍
- 三 Java多线程-ThreadPool线程池
- 二 Java多线程-线程关键字
- 二 Java 编码那些事
- 一 Java多线程-线程生命周期
- 7 Java多线程:JUC(上)