Lambda
Lambda表达式是Java SE 8中一个重要的新特性。允许你通过表达式来代替功能接口,其几乎解决了匿名内部类带来的所有问题。
其实Lambda表达式的本质是一个”语法糖”,由编译器推断并帮你转换包装为常规的代码,因此你可以使用更少的代码来实现同样的功能。
语法糖(Syntactic sugar),也译为糖衣语法,是由英国计算机科学家彼得·兰丁发明的一个术语,指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。语法糖让程序更加简洁,有更高的可读性。
匿名内部类的问题
java闭包中的匿名内部类使用的非常广泛。匿名内部类使用的最常见的场景就是事件处理器了。其次匿名内部类还常被用在多线程的程序中,我们通常写匿名内部类,而不是创建 Runnable/Callable 接口的实现类。
虽然匿名类到处都在使用,但是他们还是有很多问题。
- 第一个主要问题是复杂。这些类让代码的层级看起来很乱很复杂,也称作 Vertical Problem 。
- 第二,他们不能访问封装类的非 final 成员,this 这个关键字将变得很有迷惑性。
如果一个匿名类有一个与其封装类相同的成员名称,内部变量将会覆盖外部的成员变量,在这种情况下,外部的成员在匿名类内部将是不可见的,甚至不能通过 this 关键字来访问。因为 this 关键字值得是匿名类对象本身而不是他的封装类的对象。例子如下:
public void anonymousExample() {
String nonFinalVariable = "Non Final Example";
String variable = "Outer Method Variable";
new Thread(new Runnable() {
String variable = "Runnable Class Member";
public void run() {
String variable = "Run Method Variable";
//下面注释句子编译会出错
//System.out.println("->" + nonFinalVariable);
System.out.println("->" + variable);
System.out.println("->" + this.variable);
}
}).start();
}
//输出
->Run Method Variable
->Runnable Class Member
Functional Interfaces
在我们进一步探讨 lambda 表达式之前,让我们来看一看 Functional Interfaces。
简单来说,Functional Interfaces 是一个只有单个抽象方法的接口。(但是可以有其他方法,例如有其他继承Object而来的方法)。
大多数回调接口都是 Functional Interfaces。例如 Runnable,Callable,Comparator 等等。以前被称作 SAM(Single Abstract Method)
官方原文如下:
(The‘Single’method can exist in the form of multiple abstract methods that are inherited from superinterfaces. But in that case the inherited methods should logically represent a single method or it might redundantly declare a public method that is provided by classes like Object, e.g. toString.)
interface Runnable {
void run(); }
// 1.Functional
interface Foo {
boolean equals(Object obj); }
//2. Not functional; equals是Object类的方法
interface Bar extends Foo {
int compare(String o1, String o2); }
//3. Functional; Bar有一个抽象的不是object类的方法
interface Comparator {
boolean equals(Object obj);
int compare(T o1, T o2);
}
//4. Functional; Comparator有一个抽象的不是object类的方法,且equals是object的方法
interface Foo {