Java函数式编程(一):你好,Lambda表达式(7)
用Java原有的功能也是可以实现这些的,不过lambda表达式加了点语法糖,省掉了一些步骤,使我们的工作更简单了。这样写出的代码不仅开发更快,也更能表达我们的想法。 过去我们用的很多接口都只有一个方法:像Runnable, Callable等等。这些接口在JDK库中随处可见,使用它们的地方通常用一个函数就能搞定。原来的这些只需要一个单方法接口的库函数现在可以传递轻量级函数了,多亏了这个通过函数式接口提供的语法糖。 函数式接口是只有一个抽象方法的接口。再看下那些只有一个方法的接口,Runnable,Callable等,都适用这个定义。JDK8里面有更多这类的接口——Function, Predicate, Comsumer, Supplier等(157页,附录1有更详细的接口列表)。函数式接口可以有多个static方法,和default方法,这些方法是在接口里面实现的。 我们可以用@FunctionalInterface注解来标注一个函数式接口。编译器不使用这个注解,不过有了它可以更明确的标识这个接口的类型。不止如此,如果我们用这个注解标注了一个接口,编译器会强制校验它是否符合函数式接口的规则。 如果一个方法接收函数式接口作为参数,我们可以传递的参数包括:
1.匿名内部类,最古老的方式
2.lambda表达式,就像我们在map方法里那样
3.方法或者构造器的引用(后面我们会讲到)
如果方法的参数是函数式接口的话,编译器会很乐意接受lambda表达式或者方法引用作为参数。 如果我们把一个lambda表达式传递给一个方法,编译器会先把这个表达式转化成对应的函数式接口的一个实例。这个转化可不止是生成一个内部类而已。同步生成的这个实例的方法对应于参数的函数式接口的抽象方法。比如,map方法接收函数式接口Function作为参数。在调用map方法时,java编译器会同步生成它,就像下图所示的一样。
lambda表达式的参数必须和接口的抽象方法的参数匹配。这个生成的方法将返回lambda表达式的结果。如果返回类型不直接匹配抽象方法的话,这个方法会把返回值转化成合适的类型。 我们已经大概了解了下lambda表达式是如何传递给方法的。我们先来快速回顾一下刚讲的内容,然后开始我们lambda表达式的探索之旅。
总结
这是Java一个全新的领域。通过高阶函数,我们现在可以写出优雅流利的函数式风格的代码了。这样写出的代码,简洁易懂,错误少,利于维护和并行化。Java编译器发挥了它的魔力,在接收函数式接口参数的地方,我们可以传入lambda表达式或者方法引用。 我们现在可以进入lambda表达式以及为之改造的JDK库的世界来感觉它们的乐趣了。在下一章中,我们将从编程里面最常见的集合操作开始,发挥lambda表达式的威力。