1.1 为什么要关心Java的变化

我们的理由是,从很多方面来说,Java 8所做的改变,其影响比Java历史上任何一次改变都深远(Java 9新增了效率提升方面的重要改进,但并不伤筋动骨,这些内容本章后面会介绍。 Java 10对类型推断做了微调)。好消息是,这些改变会让编程更容易,我们再也不用编写下面这种啰唆的程序了(按照重量给inventory中的苹果排序):

  1. Collections.sort(inventory, new Comparator<Apple>() {
  2. public int compare(Apple a1, Apple a2){
  3. return a1.getWeight().compareTo(a2.getWeight());
  4. }
  5. });

使用Java 8,你能书写更简洁的代码,让代码读起来更接近问题描述本身:

  1. inventory.sort(comparing(Apple::getWeight)); ←---- 本书第一段Java 8代码

这段代码的意思是“按照重量给库存苹果排序”。目前你不用担心不理解这段代码,本书后续的章节将会介绍它做了什么,以及如何写出这样的代码。

Java 8的改变也受到了硬件的影响:平常我们用的CPU都是多核的——你的笔记本电脑或台式机的处理器可能有四个甚至更多的CPU核。然而,绝大多数现存的Java程序都只使用了其中一个核,其他三个核都闲着,或者仅消耗了它的一小部分处理能力来运行操作系统或杀毒程序。

Java 8之前,专家们可能会跟你说,只有通过多线程才能利用多个处理器核。问题是,多线程用起来不仅难,还容易出错。从Java的演进路径来看,它一直致力于让并发编程更容易、出错更少。早在1.0版本Java就引入了线程和锁,甚至还有一个内存模型——这是当时的最佳做法,然而事实证明,除非你的项目团队是由专家组成的,否则很难可靠地利用这些基本模型。Java 5添加了工业级的构建模块,如线程池和并发集合。Java 7添加了分支/合并(fork/join)框架,让并行变得更实用,然而这依旧很困难。Java 8提供了一种全新的思想,可以帮助你更容易地实现并行。然而,你仍然需要遵循一些规则,这些内容本书都会逐一介绍。

本书还会介绍Java 9新增的反应式编程支持,它是一种实现并发的结构化方法。虽然实现反应式编程有多种专有的方式,但是RxJava和Akka反应式流工具集正日益流行,已成为构建高并发系统的标准方式。

基于前文介绍的两个迫切需求(即编写更简洁的代码,以及更方便地利用处理器的多核)催生出了一座拔地而起相互勾连一致的Java 8大厦。先快速了解一下这些想法(希望能引起你的兴趣,也希望这些总结足够简洁):

  • Stream API;
  • 向方法传递代码的技巧;
  • 接口的默认方法。

Java 8提供了一个新的API(称为“流”,Stream),它支持多个数据处理的并行操作,其思路和数据库查询语言类似——从高层的角度描述需求,而由“实现”(这里是Stream库)来选择底层最佳执行机制。这样就可以避免用synchronized编写代码,这种代码不仅容易出错,而且在多核CPU2上执行所需的成本也比你想象的要高。

2多核CPU的每个处理器核都有独立的高速缓存。加锁需要这些高速缓存同步运行,然而这又需要在内核间进行较慢的缓存一致性协议通信。

从修正的角度来看,在Java 8中加入Stream可以视为添加另外两项的直接原因:向方法传递代码的简洁技巧(方法引用、Lambda)和接口中的默认方法

如果仅仅把“向方法传递代码”看成引入Stream的结果,就低估了它在Java 8中的应用范围。它提供了一种新的方式,能够简洁地表达行为参数化。比方说,你想要写两个只有几行代码不同的方法,现在只需把不同的那部分代码作为参数传递进去就可以了。采用这种编程技巧,代码更短、更清晰,也比常用的复制粘贴更少出错。高手看到这里就会想,Java 8之前可以用匿名类实现行为参数化呀——但是想想本章开头那个更加简洁的Java 8代码示例,代码本身就说明了它有多清晰!

Java 8里将代码传递给方法的功能(同时也能够返回代码并将其包含在数据结构中)还让我们能够使用一整套新技巧,通常称为函数式编程。一言以蔽之,这种被函数式编程界称为函数的代码,可以被来回传递并加以组合,以产生强大的编程语汇。这样的例子在本书中随处可见。

本章首先从宏观角度探讨语言为什么会演变,然后介绍Java 8的核心特性,接着介绍函数式编程思想——新的特性简化了使用,而且更适应新的计算机体系结构。简而言之,1.2节讨论Java的演变过程和原因,即Java以前缺乏以简易方式利用多核并行的能力。1.3节介绍为什么把代码传递给方法在Java 8里是如此强大的一个新的编程语汇。1.4节对Stream做同样的介绍:Stream是Java 8表示有序数据以及这些数据是否可以并行处理的新方式。1.5节解释如何利用Java 8中的默认方法功能让接口和库的演变更顺畅、编译更少,还会介绍Java 9中新增的模块,有了这一特性,Java系统组件就不会再被称为“只是包的JAR文件”了。最后,1.6节展望在Java和其他共用JVM的语言中进行函数式编程的思想。总的来说,本章会介绍整体脉络,而细节会在本书的其余部分中逐一展开。请尽情享受吧!