我使用Java 8编码已经有些年头,既用于新的应用程序,也用来迁移现有的应用,感受是时候写一些我发现的很是有用的“最佳实践”。程序员
我我的并不喜欢“最佳实践”这个说法,由于它意味着“一刀切”的解决方案,而编码不多是这样的工做方式——咱们须要亲自去发现什么样的解决方案才是有效的。编程
可是我发现了一些Java 8代码中能够帮助咱们的一些选择,让咱们一块儿来看看吧。数组
1.Optional架构
Optional是一个严重被低估的功能,而且有潜力删除不少困扰咱们的NullPointerExceptions。这在代码边界中(要么是正在使用的API,要么是正在暴露的API)特别有用,由于它容许你和你的调用代码来推理所期待的东西。函数
然而,不加思考和设计就应用Optional可能会致使影响大量的类,并可能致使可读性更差。下面是一些关于如何高效使用Optional的技巧。性能
Optional应该只用于返回类型学习
……不是参数,也不是字段。幸运的是,IntelliJ IDEA的让你打开检查来查看是是否遵循这些建议。测试
Optional值应在遇到它们的地方中处理。IntelliJ IDEA的建议会防止代码Optional泄漏,因此请记得在你发现Optional的地方处理它,迅速采起行动。编码
不该该简单调用get()设计
Optional的功能是表达这个值多是空的,并让你应对这种状况。所以,在对它作任何事情以前必定要检查是否有一个值。只是简单得调用get()而不先检查isPresent()在某些时候可能会致使空指针。幸运的是,IntelliJ IDEA也有检查能够提醒你这一点。
可能有更优雅的方式
结合了get()的isPresent()固然会很赞…
……但也有更优雅的解决方案。你可使用orElse在万一是空值的状况下给一个替代方案。
……或者你可使用orElseGet说明在值为空的状况下调用哪一个方法。这彷佛与上面的例子相同,但supplier方法将只在须要的时候调用,所以,若是这是一种昂贵的方法,那么使用lambda会有更佳性能。推荐阅读:JDK8新特性之Stream流。
2.使用Lambda表达式
Lambda表达式是Java 8的主要特色之一。即便你尚未使用Java 8,你如今可能已经对它们有了基本的了解。它们是用Java编程的一种新的方式,而且什么是“最佳实践”还不明显。下面是我喜欢遵循的一些指引。
保持简短
函数式程序员与较长的lambda表达式相处会更愉快,但那些淫浸于Java多年的人会发现保持lambda表达式为区区几行代码更容易。你甚至可能更愿意将其限制到一行代码,而且你能够轻松重构较长的表达式为一个方法。
这些甚至可能会成为方法引用。方法引用一开始会以为有点陌生,但实际上坚持方法引用是有价值的,由于它们在某些状况下有助于可读性,后面我会讨论到这一点。
明确
类型信息缺乏lambda表达式,因此你可能会以为包含类型信息用于参数会颇有用。
正如你所见,这回变得至关笨拙。因此我更喜欢给参数取一个有用的名字。固然,无论你有没有这么作,IntelliJ IDEA可让你看到参数得类型信息。
甚至是lambda所表明的函数式接口:
3.针对Lambda表达式设计
我认为lambda表达式有点像泛型——和泛型一块儿,咱们常用它们(例如,添加类型信息到List< >),但最好咱们能够设计一种方法或一个具备泛型类型(例如Person< T >)的类。
一样的,当使用相似于Streams API的东西时,咱们会传递lambda表达式,但更好的是创造一个须要lambda参数的方法。推荐阅读:JDK8新特性之Lambda表达式。
可是,若是你发现本身处于这类状况下,下面有一些超棒的技巧。
IntelliJ IDEA能够帮你引进函数式参数
这让你能够在有人将传递一个lambda而非Object的地方建立一个参数。此功能的好处是,它代表,现有函数式接口匹配规格说明。
这会致使…
使用现有的函数式接口
随着开发人员愈来愈熟悉Java 8代码,咱们就能知道当使用如Supplier和 Consumer的接口时,会发生什么,以及建立一个本地的ErrorMessageCreator(举个例子)可能会形成混乱,并且浪费。看看这个函数包了解一下哪些已是可用的。推荐阅读:JDK8新特性之函数式接口。
添加@FunctionalInterface到函数式接口
若是你确实须要建立本身的函数式接口,那么就这样用此注释标记。这彷佛没有太大的做用,但IntelliJ IDEA会告诉你,在你的接口不能匹配用于函数式接口的异常的时候。当你没有指定要覆盖的方法时,它会标志:
当你指定了太多方法的时候,它会标志:
而且若是你应用它到一个类而不是接口时,它会警告你:
lambda表达式可用于带有一个单一抽象方法的任何接口,但它们不能用于符合相同标准的抽象类。彷佛不合逻辑,但就是这样。
4.Stream
Stream API是Java 8另外一个大特色,而且我认为咱们还真的不知道这对咱们的编码方式会产生多大的改变。下面是我发现的一些有用的东西
排队点操做符
我我的更喜欢排队个人流操做。固然,你没有必要这样,当我发现这样作对我有帮助:
此外,在我看来,它更整洁。若是咱们按照这个模式,在减小代码行数方面咱们并无增长不少。
你可能须要调整格式设置以排列点操做符。
使用方法引用
是的,确实须要一段时间来适应这个奇怪的语法。可是,若是使用得当,它确实能够增长可读性。请看:
与(相对)新的Objects类上的辅助方法相比较:
后者的代码对于哪些值是要保存的更加明确。当lambda能够被折叠到方法参考的时候,IntelliJ IDEA一般会让你知道。
当遍历一个集合时,在可行的状况下使用Streams API
…或者新的集合方法,如forEach。IntelliJ IDEA给你建议是:
通常使用Streams API比循环和if语句的组合更加明确。例如:
IntelliJ IDEA建议这可重构为:
我所作的性能测试代表这种重构使人惊讶——并不老是可预测性能是保持不变,改善仍是变得更糟。与往常同样,若是性能在应用程序中是关键,那么在交付一种风格到另外一种以前衡量它。
遍历数组时使用循环
可是,使用Java 8并不必定意味着你必须处处使用流和新的集合方法。IntelliJ IDEA会建议转换成流,可是,这并不意味着你必须回答“yes”(记得检查是能够抑制或关闭的)。
特别是,遍历原始类型的小型数组几乎确定会用,以得到更好的性能循环,极可能(至少对于Java开发人员是新的流)更具可读性。
与任何技巧同样,规则并非一成不变的,但你应该决定是尽量地使用Streams API,仍是依然对一些操做使用循环。总之,要一致。
感兴趣的能够本身来个人Java架构群,能够获取免费的学习资料,群号:855801563 对Java技术,架构技术感兴趣的同窗,欢迎加群,一块儿学习,相互讨论。