Tips
《Effective Java, Third Edition》一书英文版已经出版,这本书的第二版想必不少人都读过,号称Java四大名著之一,不过第二版2009年出版,到如今已经将近8年的时间,但随着Java 6,7,8,甚至9的发布,Java语言发生了深入的变化。
在这里第一时间翻译成中文版。供你们学习分享之用。编程
lambda优于匿名类的主要优势是它更简洁。Java提供了一种生成函数对象的方法,比lambda还要简洁,那就是:方法引用( method references)。下面是一段程序代码片断,它维护一个从任意键到整数值的映射。若是将该值解释为键的实例个数,则该程序是一个多重集合的实现。该代码的功能是,根据键找到整数值,而后在此基础上加1:数组
map.merge(key, 1, (count, incr) -> count + incr);
请注意,此代码使用merge方法,该方法已添加到Java 8中的Map接口中。若是没有给定键的映射,则该方法只是插入给定值; 若是映射已经存在,则合并给定函数应用于当前值和给定值,并用结果覆盖当前值。 此代码表示merge方法的典型用例。ide
代码很好读,但仍然有一些样板的味道。 参数count和incr不会增长太多价值,而且占用至关大的空间。 真的,全部的lambda都告诉你函数返回两个参数的和。 从Java 8开始,Integer类(和全部其余包装数字基本类型)提供了一个静态方法总和,和它彻底相同。 咱们能够简单地传递一个对这个方法的引用,并以较少的视觉混乱获得相同的结果:函数
map.merge(key, 1, Integer::sum);
方法的参数越多,你能够经过方法引用消除更多的样板。 然而,在一些lambda中,选择的参数名称提供了有用的文档,使得lambda比方法引用更具可读性和可维护性,即便lambda看起来更长。学习
对于一个方法引用,你无能为力,由于你不能对lambda执行任何操做(只有一个难懂的异常 - 若是你好奇的话,参见JLS,9.9-2)。 也就是说,方法引用一般会致使更短,更清晰的代码。 若是lambda变得太长或太复杂,它们也会给你一个结果:你能够从lambda中提取代码到一个新的方法中,并用对该方法的引用代替lambda。 你能够给这个方法一个好名字,并把它文档记录下来。翻译
若是你使用IDE编程,它将提供替换lambda的方法,并在任何地方使用方法引用。一般状况下,你应该接受这个提议。偶尔,lambda会比方法引用更简洁。这种状况常常发生在方法与lambda相同的类中。例如,考虑这段代码,它被假定出如今一个名为GoshThisClassNameIsHumongous的类中:code
service.execute(GoshThisClassNameIsHumongous::action);
这个lambda相似于等价于下面的代码:对象
service.execute(() -> action());
使用方法引用的代码段既不比使用lambda的代码片断更短也不清晰,因此更喜欢后者。 在相似的代码行中,Function接口提供了一个通用的静态工厂方法来返回标识函数Function.identity()
。 它一般更短,更清洁,而不使用这种方法,而是使用等效的lambda内联代码:x - > x
。blog
许多方法引用是指静态方法,但有四种方法没有。 其中两个是特定(bound)和任意(unbound)对象方法引用。 在特定对象引用中,接收对象在方法引用中指定。 特定对象引用在本质上与静态引用相似:函数对象与引用的方法具备相同的参数。 在任意对象引用中,接收对象在应用函数对象时经过方法的声明参数以前的附加参数指定。 任意对象引用一般用做流管道(pipelines)中的映射和过滤方法(条目 45)。 最后,对于类和数组,有两种构造方法引用。 构造方法引用用做工厂对象。 下表总结了全部五种方法引用:接口
方法引用类型 | 举例 | 等同的Lambda |
---|---|---|
Static | Integer::parseInt | str -> Integer.parseInt(str) |
Bound | Instant.now()::isAfter | Instant then = Instant.now(); t -> then.isAfter(t) |
Unbound | String::toLowerCase | str -> str.toLowerCase() |
Class Constructor | TreeMap<K,V>::new | () -> new TreeMap<K,V> |
Array Constructor | int[]::new | len -> new int[len] |
总之,方法引用一般为lambda提供一个更简洁的选择。 若是方法引用看起来更简短更清晰,请使用它们;不然,仍是坚持lambda。