1、前言
Lambda函数的概念其实有很久远的历史了,在Lisa,C#中早有实现。且近年来,开发者对语言的表现力有了更高的要求,Java也在JDK 1.8 中引入了Lambda函数这一概念。虽然截止到写下这段文字的一刻已经过去七年之久,但其底层的设计思想仍值得我们参考一番,以便我们更好地使用。
Lambda表达式的核心思想,就是将一段函数作为参数进行传递。那要怎么实现这个目的呢?我们慢慢来看一下。
传递一个函数作为参数,这在C里面很好实现,函数指针嘛,一两个*号&号能解决的问题,C的语言特性具有先天的优势。
但是Java呢?我们都知道,Java的函数接收的参数都是对象(这个时候可以认为基本类型也是对象),可从来没听说过有函数对象这个说法啊。那要怎么整?设想有以下场景,函数executeFunc,它接收一个函数,用这个接受到的函数打印另外一个传入的变量word。
static void executeFunc(方法??,String word) {
// todo 用传入的方法打印word变量
}
2、匿名内部类写法
先介绍一种曲线救国的方式,勤劳勇敢的程序员们想出来,直接传函数不行是吧,那我就用一个接口包裹住这个方法,传接口对象进去就可以啦!好方法,我们下面来看看代码。
package main;
interface Wrapper {
void myPrint(String w);
}
class Solution {
static void executeFunc(Wrapper w, String word) {
w.myPrint(word);
}
}
确实,问题解决了。那怎么在主函数调用呢?
public static void main(String[] args) {
executeFunc(new Wrapper() {
@Override
public void myPrint(String w) {
// 个性化拓展,例如在打印之前记录时间什么的
System.out.println(w);
}
}, "Hello Lambda!");
}
看起来有一点麻烦,如果需要用executeFunc的次数多起来的时候,显然就会造成很多“不太必要”的代码了。这里说的不太必要是因为,我们必须满足编译器的需求来进行规范的语法编写,但实际上我们关心的逻辑仅仅是里面那一小段打印的语句:
// 个性化拓展,例如在打印之前记录时间什么的
System.out.println(w);
这就是lambda派上用场的地方了。
3、 Lambda写法
其实如果你在编译器编写以上代码时,你会收到一个灰色的智能提示,让你用lambda重写以上语句。
我们应用一下这个修改试试看。
public static void main(String[] args) {
executeFunc(w -> {
// 个性化拓展,例如在打印之前记录时间什么的
System.out.println(w);
}, “Hello Lambda!”);
}
我们看到,一大串的new操作,@Override重写被替换成一个传入参数,一对大括号,代码量大大减少。(实际上可以通过方法引用来进一步化简,但是在这里暂不作讨论了)