Lambda表达式的深入学习
这篇文章里面,给大家写一个比较复杂的Lambda表达式调用的例子。
首先我们定义两个接口:
public interface Worker {
void workOn(String something);
}
public interface Task {
void assignTo(Worker worker, String taskName);
}
我们写一段代码来使用上面两个接口:
public class Main {
static class Manager {
public void assignTask(Task task) {
task.assignTo(System.out::println, "日本語を学ぶ");
}
}
public static void main(String args[]) throws Exception {
Manager manager = new Manager();
manager.assignTask((worker, taskName) -> {
worker.workOn(taskName);
});
}
}
上面的代码包含了两处Lambda表达式,有一定的复杂度,我们来分析一下。首先是main()
方法里面的这处:
manager.assignTask((worker, taskName) -> {
worker.workOn(taskName);
});
manager
的assignTask()
方法接收的参数类型是Task
:
class Manager {
public void assignTask(Task task) {...}
}
因此,传入的Lambda表达式实际上是给了Task
接口里面的assignTo()
方法作为实现。因此,Lambda表达式等于帮我们定义了一个Task
的匿名实例(anonymous instance of Task)。上面的这段代码:
manager.assignTask((worker, taskName) -> {
worker.workOn(taskName);
});
就等价于:
Task task = new Task() {
@Override
public void assignTo(Worker worker, String taskName) {
worker.workOn(taskName);
}
};
manager.assignTask(task);
可以看到Lambda表达式帮我们省去了创建Task的实例的代码。
接下来我们来看Manager
这部分的代码:
static class Manager {
public void assignTask(Task task) {
task.assignTo(System.out::println, "日本語を学ぶ");
}
}
得到了Task的实例以后,在assignTask()
方法的内部就是使用task
。而Task
接口的assignTo()
方法定义如下:
public interface Task {
void assignTo(Worker worker, String taskName);
}
因此,这段Lambda表达式:
task.assignTo(System.out::println, "日本語を学ぶ");
就等价于:
Worker worker = new Worker() {
@Override
public void workOn(String something) {
System.out.println(something);
}
};
task.assignTo(worker, "日本語を学ぶ");
而根据上面对task
的分析,把两段Lambda表达式全部展开的话,整个代码如下所示:
public class Main {
static class Manager {
public void assignTask(Task task) {
Worker worker = new Worker() {
@Override
public void workOn(String something) {
System.out.println(something);
}
};
task.assignTo(worker, "日本語を学ぶ");
}
}
public static void main(String args[]) throws Exception {
Manager manager = new Manager();
Task task = new Task() {
@Override
public void assignTo(Worker worker, String taskName) {
worker.workOn(taskName);
}
};
manager.assignTask(task);
}
}
展开后的代码和使用了Lambda表达式的代码比起来,长了很多。这种多层调用的接口结构,使用了Lambda表达式以后,虽然使得代码更加整洁,但是对于新手来讲迷惑性也更强了。
然而Lambda表达式在实际的使用场景当中,这种多层的调用结构很常见,还是要多加练习加以掌握。
- 上一篇 Spacemacs vs. Cursive
- 下一篇 软件试用(一)