Effective Java 第三版——43.方法引用优于lambda表达式
Tips
《Effective Java, Third Edition》一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将近8年的时间,但随着Java 6,7,8,甚至9的发布,Java语言发生了深刻的变化。
在这里第一时间翻译成中文版。供大家学习分享之用。

43.方法引用优于lambda表达式
lambda优于匿名类的主要优点是它更简洁。Java提供了一种生成函数对象的方法,比lambda还要简洁,那就是:方法引用( method references)。下面是一段程序代码片段,它维护一个从任意键到整数值的映射。如果将该值解释为键的实例个数,则该程序是一个多重集合的实现。该代码的功能是,根据键找到整数值,然后在此基础上加1:
map.merge(key, 1, (count, incr) -> count + incr);
请注意,此代码使用merge方法,该方法已添加到Java 8中的Map接口中。如果没有给定键的映射,则该方法只是插入给定值; 如果映射已经存在,则合并给定函数应用于当前值和给定值,并用结果覆盖当前值。 此代码表示merge方法的典型用例。
代码很好读,但仍然有一些样板的味道。 参数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的类中:
service.execute(GoshThisClassNameIsHumongous::action);
这个lambda类似于等价于下面的代码:
service.execute(() -> action());
使用方法引用的代码段既不比使用lambda的代码片段更短也不清晰,所以更喜欢后者。 在类似的代码行中,Function接口提供了一个通用的静态工厂方法来返回标识函数Function.identity()。 它通常更短,更清洁,而不使用这种方法,而是使用等效的lambda内联代码:x - > x。
许多方法引用是指静态方法,但有四种方法没有。 其中两个是特定(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。
Effective Java 第三版——43.方法引用优于lambda表达式的更多相关文章
- Effective Java 第三版——61. 基本类型优于装箱的基本类型
Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...
- Effective Java 第三版——58. for-each循环优于传统for循环
Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...
- 《Effective Java 第三版》目录汇总
经过反复不断的拖延和坚持,所有条目已经翻译完成,供大家分享学习.时间有限,个别地方翻译得比较仓促,希望有疑虑的地方指出批评改正. 第一章简介 忽略 第二章 创建和销毁对象 1. 考虑使用静态工厂方法替 ...
- 《Effective Java 第三版》新条目介绍
版权声明:本文为博主原创文章,可以随意转载,不过请加上原文链接. https://blog.csdn.net/u014717036/article/details/80588806前言 从去年的3月份 ...
- effective Java 第三版学习笔记
创建对象类型的 1,静态工厂方法代替构造器 静态工厂方法有名称,不容易混乱他的作用 不必再每次调用他的时候创建实例,创建实例的代价是高的,可以重复利用缓存的对象 静态工厂甚至能返回子类对象,例如在接口 ...
- Effective Java 第三版——24. 优先考虑静态成员类
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- Effective Java 第三版——1. 考虑使用静态工厂方法替代构造方法
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- Effective Java 第三版——10. 重写equals方法时遵守通用约定
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- Effective Java 第三版——12. 始终重写 toString 方法
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
随机推荐
- C#中使用双缓冲来避免绘制图像过程中闪烁
自己所做项目中,在显示医学图像的界面中,当鼠标拖动图像时,不断刷新从后台获取新的图像,而整个过程就很诡异,一直闪个不停. 找到的一个可行方法是:在用户控件的构造函数中加入以下代码: SetStyle( ...
- css3属性(1)
text-transform语法: text-transform : none | capitalize| uppercase| lowercase 参数: none : 无转换发生 capitali ...
- Jfinal调用Orcale存储过程
因为项目需要,最近一直在学习Orcale存储过程,但发现在网上很少有人写Jave中Jfinal调用Orcale存储过程的文章,即使有也是几年前的,很多都不能用,今天给大家分享一段Jfinal调用Orc ...
- HTMLConverter使用实例(转)
---- 本来,Applet的概念相当简单——只要在Web页面中加入一个< APPLET >标记就可以了.浏览器一遇到这个标记,就会下载对应的 Applet类文件,并启动自己的解释器运行这 ...
- IE的变态
1.它自身的内容动态调试功能太简陋. 2.另存成静态网页调试,发现网页代码和原先后台写的根本不一样,能稍微守点规矩行不?
- SSH框架组建时碰到的一些问题
以前用spring+hibernate的框架解决后台事务,这一次重新组建框架,计划引入Struts,如果方便的话,可能会进一步引入Freemarker.以下记下配置中的一些问题及解决,以供他人参考. ...
- HttpDNS的坑以及一个针对安卓不太完善的测试方案
背景:单位因为域名劫持(具体表象是某个地区的用户ping不通域名或者因为DNS解析的ip跨网段导致访问速度很慢)需要运维经常去定位,于是提出了httpDNS方案. 想法是美好的,现实是残酷的.没引入这 ...
- Hadoop基础知识串烧
 YARN资源调度: 三种 FIFO 大任务独占 一堆小任务独占 capacity 弹性分配 :计算任务较少时候可以利用全部的计算资源,当队列的任务多的时候会按照比例进行资源平衡. 容量保证:保证队 ...
- maven仓库添加jar架包
推荐几个好的 Maven 常用仓库网址:http://mvnrepository.com/http://search.maven.org/http://repository.sonatype.org/ ...
- 安装ie时,报:此安装不支持您的操作系统的当前语言
打开注册表(win的"运行"栏键入 regedit 再按 OK )的HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Nls/ ...