42. lambda 表达式优于匿名类

This commit is contained in:
sjsdfg 2019-04-03 20:40:36 +08:00
parent 2562d9326a
commit e40dfe1c9f

View File

@ -96,13 +96,13 @@ public enum Operation {
```
  请注意,我们使用表示枚举常量行为的 **lambdas**`DoubleBinaryOperator` 接口。 这是 `java.util.function` 中许多预定义的函数接口之一(条目 44。 它表示一个函数,它接受两个 **double** 类型参数并返回 **double** 类型的结果。
  看看基于 **lambda**`Operation` 枚举,你可能会认为常量特定的方法体已经失去了它们的用处,但事实并非如此。 与方法和类不同,**lambda 没有名称和文档; 如果计算不是自解释的,或者超过几行,则不要将其放入 lambda 表达式中。** 一行代码对于 **lambda** 说是理想的,三行代码是合理的最大值。 如果违反这一规定,可能会严重损害程序的可读性。 如果一个 **lambda** 很长或很难阅读,要么找到一种方法来简化它或重构你的程序来消除它。 此外,传递给枚举构造方法的参数在静态上下文中进行评估。 因此,枚举构造方法中的 **lambda** 表达式不能访问枚举的实例成员。 如果枚举类型具有难以理解的常量特定行为,无法在几行内实现,或者需要访问实例属性或方法,那么常量特定的类主体仍然是行之有效的方法。
  同样,你可能会认为匿名类在 **lambda** 时代已经过时了。 这更接近事实,但有些事情你可以用匿名类来做,而却不能用 **lambdas** 做。 **Lambda** 仅限于函数式接口。 如果你想创建一个抽象类的实例,你可以使用匿名类来实现,但不能使用 **lambda**。 同样,你可以使用匿名类来创建具有多个抽象方法的接口实例。 最后,**lambda** 不能获得对自身的引用。 在 **lambda** 中,`this` 关键字引用封闭实例,这通常是你想要的。 在匿名类中,`this` 关键字引用匿名类实例。 如果你需要从其内部访问函数对象,则必须使用匿名类。
  **Lambdas** 与匿名类共享无法可靠地序列化和反序列化实现的属性。**因此,应该很少 (如果有的话) 序列化一个 lambda(或一个匿名类实例)。** 如果有一个想要进行序列化的函数对象,比如一个 `Comparator`,那么使用一个私有静态嵌套类的实例(条目 24
  综上所述,从 Java 8 开始,**lambda** 是迄今为止表示小函数对象的最佳方式。 **除非必须创建非函数式接口类型的实例,否则不要使用匿名类作为函数对象。** 另外,请记住,**lambda** 表达式使代表小函数对象变得如此简单,以至于它为功能性编程技术打开了一扇门,这些技术在 Java 中以前并不实用。