第43条 方法引用优先于Lambda
- 方法引用相比于lambda表达式更加简洁
- 有时候Lambda会比方法引用更加简洁明了,Lambda的参数名称会使Lambda表达式的可读性更强
- 当方法引用比lambda更加简洁的时候,就用方法引用,否则就用lambda
第44条 坚持使用标准的函数接口
-
有了lambda之后,模板方法(Template Method)模式就没有吸引力了,现代的方法是提供一个接收函数对象的静态工厂或者构造函数来达到相同的效果
-
6个基本的函数式接口
接口 范例 UnaryOperator<T>
String::toLowerCase
BinaryOperator<T>
BigInteger::add
Predicate<T>
Collection::isEmpty
Function<T, R>
Arrays::asList
Supplier<T>
Instant::now
Consumer<T>
System.out::println
-
不要用带包装类型的基础函数接口代替基本函数接口,会因为不断地拆箱装箱带来性能问题
-
用注解
@FunctionalInterface
标记自定义函数式接口- 告诉其他人这个接口是为了Lambda设计的
- 保证这个接口不会编译,除非它只有一个方法
- 避免后续的维护人员不小心给该接口添加抽象方法
-
不要给同一个方法提供函数式接口在同一个参数位置的重载(有可能会引起二义性)。比如
ExecutorService
的submit
方法就有Callable<T>
和Runnable
的重载。比较极端的例子:@FunctionalInterface public interface FakeRunnable { void run(); } public class JustInterface { public void doSomething(Runnable runnable) { runnable.run(); } public void doSomething(FakeRunnable fakeRunnable) { fakeRunnable.run(); } } public static void main(String[] args) { new JustInterface().doSomething(() -> System.out.println("1")); }
这时候就会报错,因为这个lambda表达式并不能知道具体是哪个方法
-
如果要自己编写函数式接口,需要考虑3个要素(类比
Comparator
):- 通用, 会得益于有一个描述性的名字
- 与一个很强的协议相关
- 得益于自定义的默认方法
思考
- 比起模板方法,其实策略模式更适合使用
Function
,模板方法更有可能需要访问类里面的成员 - 如果仅仅使用标准函数接口不能太表意,我个人更倾向于再编写一个自己的函数式接口,更具体的表达这个接口的作用
- 我个人不喜欢将函数接口作为一个参数传递给方法,尤其是标准函数接口。这种情况下很难理解这个参数的作用是什么,代码的可读性很低,我宁愿自己再编写一个新的接口
- 其实不管意图是不是像要让接口面向Lambda,都可以在只有一个方法的情况下标记接口是
@FunctionalInterface
,一个是让接口简洁,更容易达到接口隔离原则,另外就是如果真的有一个接口的实现非常简单,就不需要单独新建一个Java文件编写实现了,也可以稍微提高编译的速度
网友评论