前言

本书基于Java 8的特性进行该语言的编程教学。

我以前的那本Java书——《Java编程思想》(第4版),对于用Java 5编程仍然很有用,Android编程用的就是这个语言版本。然而随着Java 8的到来,这门语言发生了许多显著的变化,使得编写和阅读新版本Java代码的方式都与以往有了明显的不同。于是,花费两年时间编写一本新书也就在情理之中了。

本书的读者具备基础的编程经验即可。对于经验不足的编程入门者而言,可汗学院(Khan Academy)这类网络资源提供了不少介绍编程基础知识的课程,另外也可以尝试之前提及的“Thinking in C”免费多媒体课程。当你遇到问题时,相比数年前只能依靠纸质媒体的时代,如今通过YouTube、博客、Stack Overflow等网站就可以轻松地找到所需要的答案。此外,若有坚韧不拔的毅力,你完全可以把本书当作自己的第一本编程教材。此外,本书同样适用于那些希望拓宽自己知识面的专业程序员。

《Java编程思想》一书自面世至今,让我受益匪浅,尤其是与其相关的全球范围内的演讲让我收获很多。对此,我一直心存感激。而这本书真正的无价之处在于,它让许多人和公司之间产生了关联。

本书目标

本书每一章都会介绍一个或者一组互相关联的概念,同时这些概念不依赖于当前章节没有介绍的特性。因此,你可以结合当前获取的知识来充分理解上下文,然后再阅读下一章。

我个人对本书的目标如下。

  1. 循序渐进地呈现相关知识点,以便你充分理解每一个理念,之后再继续前行。同时,谨慎地安排语言特性出现的顺序,以便你先学习一个特性,然后再接触与之相关的实际应用场景。然而我并不能保证百分之百可以做到这一点,当出现意外情况时,我也会提供一些简要的相关说明。
  2. 所使用的示例尽可能地浅显易懂。有时候我会因为这一条原则而放弃引入所谓“现实世界”的问题,然而我发现对于初学者而言,相比于因为示例解决了一个范围很大的问题而惊讶,当他们理解示例中所有细节的时候会觉得更有收获。对于这一点,也许有人会批判我只热衷于“简单示例”,但是为了产生更为明显的教育成效,我依然乐于接受目前的做法。
  3. 相较传授我所了解的语言知识,我更希望传授语言的重要之处是什么。我认为信息需要根据其重要程度进行分级,而事实是,有些细节对于95%的程序员而言是无关紧要的。这些细节只会让人们感到困惑,以及增加他们对于语言复杂度的认知。如果你的代码必须考虑这些细节,切记这些内容也会困扰那些阅读和维护代码的人。所以我提倡代码使用简单的实现方式。
  4. 为你打下坚实的编程语言基础,以便你之后学习难度更高的课程和图书时,可以充分理解自己所遇到的问题。

语言设计缺陷

每一种语言都存在设计缺陷。屡屡让新手程序员感到不安和挫败的是,他们必须“周旋”于各种语言特性之中,不断猜测应该用什么、不应该用什么。承认错误总是让人感到不快,但是相比承认错误所带来的不适感,这种糟糕的新手体验要严重得多。令人尴尬的是,所有失败的语言/库设计一直存在于Java的发布版本里。

诺贝尔经济学奖得主Joseph Stiglitz有一句生活哲言十分应景,也叫作“承诺升级理论”(The Theory of Escalating Commitment):

持续犯错的代价由别人承担,而承认错误的代价由你自己来承担。

如果你读过我以往的文章或著作,就会知道,当发现编程语言的设计缺陷时,我倾向于指出这些问题。Java发展到今天,已拥有了许多热心的拥护者,其中有些人甚至将Java视为自家“孩子”,而非一种语言工具。因为我编写了一些关于Java的著作,所以他们以为我也会像他们一样袒护Java。于是,当我发现了某个语言缺陷并进行批判时,经常会出现以下两种情况。

  1. 起初会引起一阵类似于“我的孩子无论对错”的愤怒,之后会逐渐平复,变成只有零星反抗。到了最后(也许会经过许多年),该缺陷逐渐被大家广泛承认,从此被视为Java的历史遗留问题。
  2. 更为关键的是,新手程序员并没有经历过“想不通为什么会这样”的痛苦挣扎,尤其是发现了某个看起来不对劲儿的地方之后所产生的自我怀疑,在这种情况下人们会很自然地认为要么是自己做错了,要么就是自己还没有搞明白。更糟糕的是,有些教授该语言的人会直接引用一些错误的概念,而不是对问题进行更加深入的研究和分析。而如果能够理解语言的设计缺陷,即使是新手程序员也能够理解不对劲儿的地方是一个错误,从而绕过它继续前行。

我认为,理解语言和库的设计缺陷是必要的,因为它们会影响程序员的生产力。有些公司和团队会刻意规避某些语言特性,因为虽然它们看起来很有趣,但可能会在你毫无准备之时突然卡住你的工作进程。此外,设计缺陷也会影响新语言的创建和采用。探索一门语言能做什么的过程十分有趣,然而设计缺陷能够告诉你该语言不能做什么。

多年以来,我真切地感受到Java语言的设计者不够关心用户。有些语言缺陷可谓是太过明显,根本没有经过深思熟虑,看起来像是设计者的思绪早已飞到了九霄云外,对自己的用户不管不顾。因此,Java语言在相当长的一段时间里饱受争议,也许这些有争议之处正是其诱惑所在。此外,这种对程序员看似不尊重的态度,也是我当初放弃Java选择其他语言,并且在相当长的一段时间内都不想回头的主要原因。

而当我重新回过头来审视Java的时候,Java 8给我的感觉是焕然一新,就好像是该语言的设计者对于语言和用户的态度发生了180度大转变。比如,许多被用户诟病已久,甚至被视为语言毒瘤的特性和库都得到了修正。新引入的特性也让人耳目一新,就好像是设计团队中新加入了几位极其关注程序员使用体验的设计者。这些特性最终被证明是有效的,从而使得Java语言更为出众,这明显好过在没有深入探究一个理念的本质时就急不可待地把它添加进来。此外,部分新特性十分优雅(至少可以说在考虑到Java局限性的情况下,已经尽可能地优雅了)。对此我只能猜测,可能有些人离开了Java语言设计团队,因而才发生了这些变化。

得益于语言设计者的良苦用心(其实我并没有料想到这一点),编写本书的过程相比以往要顺利得多。Java 8包含了许多基础和重要的改进,而由于Java的向后兼容性一直惨不忍睹,做出这些改进无疑需要花费相当多的精力。因此可以预料的是,将来也很难再见到如此重大的改进了(关于这一点,希望我是错的)。话虽如此,我依然要为那些把Java重新带入正确航道的人献上掌声。当终于能够用Java 8编写出某段代码时,我第一次下意识地喊出:“我爱死这个了!”

最后,本书的出版时机也非常不错,这是因为Java 8提供的一些重要特性会大大影响我们编写代码的方式,而到目前为止,Java 9似乎专注于改进语言的底层,其引入的一些重要的底层特性并不会影响本书中的代码。

经过测试的示例

本书提供的示例所使用的是Java 8环境和Gradle编译工具。虽然我也使用新版本的Java测试过这些示例,但我依然推荐你使用该语言的长期稳定(LTS)版本:在我写这本书时,对应的是Java 8或者Java 11。此外,本书所有示例都可以从GitHub仓库免费获取。

每当构建一个应用程序时,如果没有一套内置测试流程来测试你的代码,就无法判断代码是否坚实可信。因此,我为本书创建了一套测试系统,用于展示和验证大多数示例的输出结果。具体而言,运行示例代码后的输出结果会生成一段注释,附加在代码的末尾处。有时候注释并不显示全部内容,而是只显示开头的几行,或者开头和末尾的几行。这种嵌入式的输出方式提升了代码可读性,降低了学习门槛,同时也提供了一种验证代码正确性的方式。

普及程度

Java的普及具有重要意义。我的意思是,如果你学会了Java,也许找工作会容易一些,而且市面上有大量的Java培训材料、课程以及其他学习资源等。另外,如果你开一家公司并且选择Java作为工作语言,招募Java程序员时也会容易一些。Java的这一点优势确实无可争辩。

话虽如此,目光短浅总归不是好事。如果你并不是真心喜爱Java,建议你还是远离它为好。我的意思是,如果学习Java只是为了找工作,无异于选择了一种不幸福的人生。而对于公司来说,如果你选择Java只是为了降低招聘难度,请务必三思而后行。根据你的实际需求,也许采用其他语言的话,你可以雇用更少的员工,但能达到更高的生产力(比如通过我的另一本书Atomic Kotlin学习Kotlin语言)。此外,使用一种更新也更激动人心的编程语言也许更容易吸引有志之士的加盟。

不过,如果你真的喜爱Java这门语言,那么欢迎你加入。同时,我希望本书可以丰富你的编程经验。

关于Android程序员

Android编程使用的环境是Java 5,而我编写本书的原则是“尽可能使用纯粹的Java 8”,所以如果你学习Java的目的是为Android系统编写应用程序,那么推荐你学习《Java编程思想》(第4版)。此外,还有许多专门针对Android的编程资源可供学习。

顺便一提,对于Android编程而言,Kotlin语言是一种更新和更好的选择,同时它也是Android的官方编程语言。

出版说明

本书使用了自动化的构建过程,同样的自动化过程还有解压、编译以及测试所有示例代码。我使用Python 3编写了大量的应用程序来处理所有的自动化过程。

封面设计

本书的封面插图来自美国公共事业振兴署(Works Progress Administration,简称WPA,是1935—1943年美国大萧条时期所创建的一个大型公共事业项目,其目标是援助失业人口重新返回工作岗位)。此外,它也让我想起了《绿野仙踪》系列丛书的插图。我的设计师朋友Daniel Will-Harris和我都十分喜爱这张图片。

致谢

感谢Eric Evans(《领域驱动设计》一书的作者)针对本书书名提供了宝贵意见,也感谢所有在讨论组里帮助我确定书名的人们。

感谢James Ward,他使我得以为本书使用Gradle构建工具,感谢他一直以来提供的帮助以及跟我的友谊。感谢Ben Muschko对构建文件所做的优化,同时也要感谢Hans Dockter给Ben时间来做这件事。

感谢Jeremy Cerise与Bill Frasure参与本书的开发者活动,并提供了有价值的帮助。

感谢所有抽出宝贵时间莅临科罗拉多州克雷斯特德比特市,参加我所组织的会议、研讨活动、开发者活动以及其他活动的嘉宾们。你们虽深居幕后,但所做出的贡献不可或缺。

献词

谨献给我敬爱的父亲E. Wayne Eckel,他生于1924年4月1日,卒于2016年11月23日。