From edfebaf56c646d6aa4fcd1bbc97d2e9ee998da0c Mon Sep 17 00:00:00 2001
From: PEGASUS <32333727+PEGASUS1993@users.noreply.github.com>
Date: Thu, 10 Sep 2020 17:13:00 +0800
Subject: [PATCH 01/68] =?UTF-8?q?Preface=20=E7=BF=BB=E8=AF=91=E4=BC=98?=
=?UTF-8?q?=E5=8C=96=20(#565)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* Update 00-Preface.md
* Update 00-On-Java-8.md
* Update 00-Preface.md
* Update 00-Preface.md
---
docs/book/00-On-Java-8.md | 11 ++++++-----
docs/book/00-Preface.md | 12 ++++++------
2 files changed, 12 insertions(+), 11 deletions(-)
diff --git a/docs/book/00-On-Java-8.md b/docs/book/00-On-Java-8.md
index c11bde4d..a7d91f09 100644
--- a/docs/book/00-On-Java-8.md
+++ b/docs/book/00-On-Java-8.md
@@ -51,13 +51,14 @@
-本书出版自美国,版权所有,翻版必究。未经授权不得非法存储在检索系统中,或以电子,机械,影印,录制任何形式传输等。制造商和销售商使用商标用来区分其产品标识。如果这些名称出现在这本书中,并且出版商知道商标要求,则这些名称已经用大写字母或所有大写字母打印。
+本书出版自美国,版权所有,翻版必究。未经授权,不得非法存储在检索系统中,或以电子,机械,影印,录制等形式传播。制造商和销售商使用商标用来区分其产品标识。如果这些名称出现在这本书中,并且出版商知道商标要求,则这些名称已经用大写字母或所有大写字母打印。
Java 是甲骨文公司(Oracle. Inc.)的商标。Windows 95,Windows NT,Windows 2000,Windows XP,Windows 7,Windows 8 和 Windows 10 是微软公司(Microsoft Corporation)的商标。
-此处提及的所有其他产品名称和公司名称均为其各自所有者的财产。作者和出版商在编写本书时已经仔细校对过,但不作任何明示或暗示的保证,对错误或遗漏不承担任何责任。对于因使用此处包含的信息或程序而产生的偶然或间接损失,我们不承担任何责任。
+此处提及的所有其他产品名称和公司名称均为其各自所有者的财产。
-这本书是以平板电脑和计算机为载体的电子书,非传统纸质版书籍。
-故所有布局和格式设计旨在优化您在各种电子书阅读平台和系统上的观看体验。
+作者和出版社在编写本书时已经仔细校对过,但不作出任何形式的保证,也不承担任何错误或遗漏的责任。对于使用本协议中包含的信息或程序而产生的附带或间接损失,本协议不承担任何责任。
+
+本书是为平板电脑和计算机设备制作的的电子书,非传统纸质版书籍。 因此所有布局和格式设计旨在优化您在各种电子书阅读平台和系统上的观看体验。
封面由 Daniel Will-Harris 设计,[www.Will-Harris.com](http://www.Will-Harris.com)。
-
\ No newline at end of file
+
diff --git a/docs/book/00-Preface.md b/docs/book/00-Preface.md
index d614e816..903b92e5 100644
--- a/docs/book/00-Preface.md
+++ b/docs/book/00-Preface.md
@@ -5,13 +5,13 @@
我之前的 Java 书籍 *Thinking in Java, 4th Edition*(《Java编程思想 (第4版)》 Prentice Hall 2006)依然适用于 Java 5 编程,在此版本 Java 语言开始用作 Android 编程。此后,这门语言的许多地方发生了翻天覆地的变化,特别是 Java 8 的转变,以至于新的 Java 代码读起来的感觉也不尽相同。这也促使我时隔多年,创作了这本新书。
-《On Java 8》旨在面向已具有编程基础的开发者们。对于初学者,可以先在 [Code.org](http://Code.org) 或者 [Khan Academy](https://www.khanacademy.org/computing/computer-programming) 等网站补充必要的前置知识。同时,[OnJava8.com](http://www.OnJava8.com) 上也有免费的 Thinking in C(《C编程思想》)专题知识。与几年前我们依赖印刷媒体时相比,像 YouTube、博客和 StackOverFlow 这样的网站使得寻找答案变得非常简单。如果将本书作为编程入门书籍,请结合这些学习途径努力坚持下去。同时,本书也适合想要扩展知识的在职程序员。
+《On Java 8》旨在面向已具有编程基础的开发者们。对于初学者,可以先在 [Code.org](http://Code.org) 或者 [可汗学院Khan Academy](https://www.khanacademy.org/computing/computer-programming) 等网站补充必要的预备知识。同时,[OnJava8.com](http://www.OnJava8.com) 上也有免费的 Thinking in C(《C编程思想》)专题知识。与几年前我们依赖印刷媒体时相比,像 YouTube、博客和 StackOverFlow 这样的网站使得寻找答案变得非常简单。如果将本书作为编程入门书籍,请结合这些学习途径努力坚持下去。同时,本书也适合想要扩展知识的专业程序员。
得益于《*Thinking in Java*》,我得以到世界各地演讲,我对此由衷感激。它为我的 [Reinventing Business](http://www.reinventing-business.com) 项目在与人员及公司建立联系方面提供了宝贵的帮助。我最终撰写本书的原因之一就是想支持这一项目的研究,而下一个合乎逻辑的步骤似乎是实际创建一个所谓的蓝绿色组织(Teal Organization)。我希望本书可以成为该项目的一种众筹。
## 教学目标
-每章教授一个或一组相关的概念,并且这些知识不依赖于尚未学习到的章节。如此,学习者可以在当前知识的背景框架下循序渐进地掌握 Java。
+每章讲授一个或一组相关的概念,并且这些知识不依赖于尚未学习到的章节。如此,学习者可以在当前知识的背景框架下循序渐进地掌握 Java。
本书的教学目标:
@@ -51,9 +51,9 @@
书中代码示例基于 Java 8 和 Gradle 编译构建,并且代码示例都保存在[这个自由访问的GitHub的仓库](https://github.com/BruceEckel/OnJava8-Examples) 中。我们需要内置的测试框架,以便于在每次构建系统时自动运行。否则,你将无法保证自己代码的可靠性。为了实现这一点,我创建了一个测试系统来显示和验证大多数示例的输出结果。这些输出结果我会附加在示例结尾的代码块中。有时仅显示必要的那几行或者首尾行。利用这种方式来改善读者的阅读和学习体验,同时也提供了一种验证示例正确性的方法。
-## 普及性
+## 受欢迎度
-Java 的普及性对于其受欢迎程度有重要意义。学习 Java 会让你更容易找到工作。相关的培训材料,课程和其他可用的学习资源也很多。对于企业来说,招聘 Java 程序员相对容易。如果你不喜欢 Java 语言,那么最好不要拿他当作你谋生的工具,因为这种生活体验并不好。作为一家公司,在技术选型前一定不要单单只考虑 Java 程序员好招。每种语言都有其适用的范围,有可能你们的业务更适用于另一种编程语言来达到事半功倍的效果。如果你真的喜欢 Java,那么欢迎你。希望这本书能丰富你的编程经验!
+Java的受欢迎程度具有重要意义。学习 Java 会让你更容易找到工作。相关的培训材料,课程和其他可用的学习资源也很多。对于使用Java的初创企业来说,招聘 Java 程序员相对容易。如果你真的不喜欢 Java 语言,那么最好不要使用它————仅仅为了找工作而使用它,并不是一个快乐的生活选择。作为一家公司,在技术选型前一定不要单单只考虑容易招聘Java 程序员。每种语言都有其适用的范围,有可能另一种编程语言更适用于你们的业务,来达到事半功倍的效果。如果你真的喜欢 Java,那么欢迎你。希望这本书能丰富你的编程经验!
## 关于安卓
@@ -93,8 +93,8 @@ Java 的普及性对于其受欢迎程度有重要意义。学习 Java 会让你
## 献礼
-> 谨以此书献给我敬爱的父亲 E. Wayne Eckel。
-> 1924年4月1日至2016年11月23日
+> 谨以此书献给我敬爱的父亲 E. Wayne Eckel
+> (1924.4.1 ~ 2016.11.23)。
From b677bca1fe303f4939f31df92f99e567d7aa0ac3 Mon Sep 17 00:00:00 2001
From: xiguazhiPrince <34903051+xiguazhiPrince@users.noreply.github.com>
Date: Thu, 10 Sep 2020 20:43:34 +0800
Subject: [PATCH 02/68] =?UTF-8?q?=E5=B0=86=E2=80=9C=E7=BB=A7=E6=89=BF?=
=?UTF-8?q?=E5=86=8DAbstractCollection=E2=80=9D=20=E4=BF=AE=E6=94=B9?=
=?UTF-8?q?=E4=B8=BA=E5=86=8D=E7=BB=A7=E6=89=BF=20(#569)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
将“继承再AbstractCollection” 修改为再继承
From ccbe03fed1c8dfade10d33d6ff1ab9dffd56ee02 Mon Sep 17 00:00:00 2001
From: Lane
Date: Thu, 10 Sep 2020 20:43:56 +0800
Subject: [PATCH 03/68] Update 11-Inner-Classes.md (#568)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
让粗体显示正常
---
docs/book/11-Inner-Classes.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/book/11-Inner-Classes.md b/docs/book/11-Inner-Classes.md
index 3265c2fc..3a6ac3bd 100644
--- a/docs/book/11-Inner-Classes.md
+++ b/docs/book/11-Inner-Classes.md
@@ -1419,9 +1419,9 @@ Anonymous inner 9
## 内部类标识符
-由于编译后每个类都会产生一个**.class** 文件,其中包含了如何创建该类型的对象的全部信息(此信息产生一个"meta-class",叫做 **Class** 对象)。
+由于编译后每个类都会产生一个 **.class** 文件,其中包含了如何创建该类型的对象的全部信息(此信息产生一个"meta-class",叫做 **Class** 对象)。
-你可能猜到了,内部类也必须生成一个**.class** 文件以包含它们的 **Class** 对象信息。这些类文件的命名有严格的规则:外部类的名字,加上“**$**",再加上内部类的名字。例如,**LocalInnerClass.java** 生成的 **.class** 文件包括:
+你可能猜到了,内部类也必须生成一个 **.class** 文件以包含它们的 **Class** 对象信息。这些类文件的命名有严格的规则:外部类的名字,加上“**$**”,再加上内部类的名字。例如,**LocalInnerClass.java** 生成的 **.class** 文件包括:
```java
Counter.class
From 706827c54cc99d5122439e164b061090fc2dcb18 Mon Sep 17 00:00:00 2001
From: Lane
Date: Fri, 11 Sep 2020 15:32:28 +0800
Subject: [PATCH 04/68] Update 11-Inner-Classes.md (#570)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 双引号挪到 `**` 内部
- 使用英文双引号(否则 gitbook 下显示 怪异)
- 添加必要空格,
- java => Java
---
docs/book/11-Inner-Classes.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/docs/book/11-Inner-Classes.md b/docs/book/11-Inner-Classes.md
index 3a6ac3bd..ea329e45 100644
--- a/docs/book/11-Inner-Classes.md
+++ b/docs/book/11-Inner-Classes.md
@@ -1421,7 +1421,7 @@ Anonymous inner 9
由于编译后每个类都会产生一个 **.class** 文件,其中包含了如何创建该类型的对象的全部信息(此信息产生一个"meta-class",叫做 **Class** 对象)。
-你可能猜到了,内部类也必须生成一个 **.class** 文件以包含它们的 **Class** 对象信息。这些类文件的命名有严格的规则:外部类的名字,加上“**$**”,再加上内部类的名字。例如,**LocalInnerClass.java** 生成的 **.class** 文件包括:
+你可能猜到了,内部类也必须生成一个 **.class** 文件以包含它们的 **Class** 对象信息。这些类文件的命名有严格的规则:外部类的名字,加上 **"$"** ,再加上内部类的名字。例如,**LocalInnerClass.java** 生成的 **.class** 文件包括:
```java
Counter.class
@@ -1430,9 +1430,9 @@ LocalInnerClass$LocalCounter.class
LocalInnerClass.class
```
-如果内部类是匿名的,编译器会简单地产生一个数字作为其标识符。如果内部类是嵌套在别的内部类之中,只需直接将它们的名字加在其外部类标识符与“**$**”的后面。
+如果内部类是匿名的,编译器会简单地产生一个数字作为其标识符。如果内部类是嵌套在别的内部类之中,只需直接将它们的名字加在其外部类标识符与 **"$"** 的后面。
-虽然这种命名格式简单而直接,但它还是很健壮的,足以应对绝大多数情况。因为这是 java 的标准命名方式,所以产生的文件自动都是平台无关的。(注意,为了保证你的内部类能起作用,Java 编译器会尽可能地转换它们。)
+虽然这种命名格式简单而直接,但它还是很健壮的,足以应对绝大多数情况。因为这是 Java 的标准命名方式,所以产生的文件自动都是平台无关的。(注意,为了保证你的内部类能起作用,Java 编译器会尽可能地转换它们。)
From 0acae8e1324b25814ec427dadd01ba0a4e086689 Mon Sep 17 00:00:00 2001
From: Hongkuan Wang
Date: Sun, 13 Sep 2020 18:12:21 +0300
Subject: [PATCH 05/68] =?UTF-8?q?=E8=BD=AC=E4=B9=89=E5=A4=A7=E4=BA=8E?=
=?UTF-8?q?=E5=8F=B7=E5=92=8C=E5=B0=8F=E4=BA=8E=E5=8F=B7=20(#574)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
docs/book/12-Collections.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/book/12-Collections.md b/docs/book/12-Collections.md
index 49326b79..269fc785 100644
--- a/docs/book/12-Collections.md
+++ b/docs/book/12-Collections.md
@@ -771,7 +771,7 @@ public class Stack {
}
```
-这里引入了使用泛型的类定义的最简单的可能示例。类名称后面的 **** 告诉编译器这是一个参数化类型,而其中的类型参数 **T** 会在使用类时被实际类型替换。基本上,这个类是在声明“我们在定义一个可以持有 **T** 类型对象的 **Stack** 。” **Stack** 是使用 **ArrayDeque** 实现的,而 **ArrayDeque** 也被告知它将持有 **T** 类型对象。注意, `push()` 接受类型为 **T** 的对象,而 `peek()` 和 `pop()` 返回类型为 **T** 的对象。 `peek()` 方法将返回栈顶元素,但并不将其从栈顶删除,而 `pop()` 删除并返回顶部元素。
+这里引入了使用泛型的类定义的最简单的可能示例。类名称后面的 **\** 告诉编译器这是一个参数化类型,而其中的类型参数 **T** 会在使用类时被实际类型替换。基本上,这个类是在声明“我们在定义一个可以持有 **T** 类型对象的 **Stack** 。” **Stack** 是使用 **ArrayDeque** 实现的,而 **ArrayDeque** 也被告知它将持有 **T** 类型对象。注意, `push()` 接受类型为 **T** 的对象,而 `peek()` 和 `pop()` 返回类型为 **T** 的对象。 `peek()` 方法将返回栈顶元素,但并不将其从栈顶删除,而 `pop()` 删除并返回顶部元素。
如果只需要栈的行为,那么使用继承是不合适的,因为这将产生一个具有 **ArrayDeque** 的其它所有方法的类(在[附录:集合主题]()中将会看到, **Java 1.0** 设计者在创建 **java.util.Stack** 时,就犯了这个错误)。使用组合,可以选择要公开的方法以及如何命名它们。
From 12b5813041df2d7bad7f206cae89d29065e05cec Mon Sep 17 00:00:00 2001
From: Lane
Date: Sun, 13 Sep 2020 23:12:41 +0800
Subject: [PATCH 06/68] make sidebar appearance corrent (#573)
---
docs/index.html | 45 ++++++++--------
docs/sidebar.md | 133 ++++++++++++++++++++++++++++++++----------------
2 files changed, 113 insertions(+), 65 deletions(-)
diff --git a/docs/index.html b/docs/index.html
index 7f54b8af..b7e41098 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -55,6 +55,11 @@
/*font-family: Microsoft YaHei, Source Sans Pro, Helvetica Neue, Arial, sans-serif !important;*/
}
+ .sidebar, .sidebar-nav {
+ padding-left: 10px;
+ padding-right: 10px;
+ }
+
.markdown-section>p {
font-size: 16px !important;
}
@@ -66,7 +71,7 @@
/*.anchor span {
color: rgb(66, 185, 131);
- }*/
+ }*/
section.cover h1 {
margin: 0;
@@ -345,29 +350,29 @@
window.$docsify = {
name: '《On Java 8》中文版',
repo: 'https://github.com/LingCoder/OnJava8',
- // loadSidebar: true,
- subMaxLevel: 3,
- search: {
- paths: 'auto',
- placeholder: '🔍 点击搜索 ',
- noData: '😞 没有结果! ',
- // Headline depth, 1 - 6
- depth: 6
+ loadSidebar: 'sidebar.md',
+ // subMaxLevel: 3,
+ search: {
+ paths: 'auto',
+ placeholder: '🔍 点击搜索 ',
+ noData: '😞 没有结果! ',
+ // Headline depth, 1 - 6
+ depth: 6
+ },
+ copyCode: {
+ buttonText : '复制',
+ errorText : 'Error',
+ successText: 'OK!'
+ },
+ pagination: {
+ previousText: '上一章节',
+ nextText: '下一章节',
},
- copyCode: {
- buttonText : '复制',
- errorText : 'Error',
- successText: 'OK!'
- },
- pagination: {
- previousText: '上一章节',
- nextText: '下一章节',
- },
- coverpage: true
+ coverpage: true,
}
-
+
diff --git a/docs/sidebar.md b/docs/sidebar.md
index d1d99dcd..e79c07a0 100644
--- a/docs/sidebar.md
+++ b/docs/sidebar.md
@@ -1,9 +1,13 @@
-#### [译者的话](README.md)
-#### [封面](book/00-On-Java-8.md)
-#### [前言](book/00-Preface.md)
-#### [简介](book/00-Introduction.md)
-## [第一章 对象的概念](book/01-What-is-an-Object.md)
+### [译者的话](README.md)
+
+### [封面](book/00-On-Java-8.md)
+
+### [前言](book/00-Preface.md)
+
+### [简介](book/00-Introduction.md)
+
+### [第一章 对象的概念](book/01-What-is-an-Object.md)
* [抽象](book/01-What-is-an-Object.md#抽象)
* [接口](book/01-What-is-an-Object.md#接口)
* [服务提供](book/01-What-is-an-Object.md#服务提供)
@@ -16,13 +20,15 @@
* [生命周期](book/01-What-is-an-Object.md#生命周期)
* [异常处理](book/01-What-is-an-Object.md#异常处理)
* [本章小结](book/01-What-is-an-Object.md#本章小结)
-## [第二章 安装Java和本书用例](book/02-Installing-Java-and-the-Book-Examples.md)
+
+### [第二章 安装Java和本书用例](book/02-Installing-Java-and-the-Book-Examples.md)
* [编辑器](book/02-Installing-Java-and-the-Book-Examples.md#编辑器)
* [Shell](book/02-Installing-Java-and-the-Book-Examples.md#Shell)
* [Java安装](book/02-Installing-Java-and-the-Book-Examples.md#Java安装)
* [校验安装](book/02-Installing-Java-and-the-Book-Examples.md#校验安装)
* [安装和运行代码示例](book/02-Installing-Java-and-the-Book-Examples.md#安装和运行代码示例)
-## [第三章 万物皆对象](book/03-Objects-Everywhere.md)
+
+### [第三章 万物皆对象](book/03-Objects-Everywhere.md)
* [对象操纵](book/03-Objects-Everywhere.md#对象操纵)
* [对象创建](book/03-Objects-Everywhere.md#对象创建)
* [代码注释](book/03-Objects-Everywhere.md#代码注释)
@@ -32,7 +38,8 @@
* [小试牛刀](book/03-Objects-Everywhere.md#小试牛刀)
* [编码风格](book/03-Objects-Everywhere.md#编码风格)
* [本章小结](book/03-Objects-Everywhere.md#本章小结)
-## [第四章 运算符](book/04-Operators.md)
+
+### [第四章 运算符](book/04-Operators.md)
* [开始使用](book/04-Operators.md#开始使用)
* [优先级](book/04-Operators.md#优先级)
* [赋值](book/04-Operators.md#赋值)
@@ -50,7 +57,8 @@
* [Java没有sizeof](book/04-Operators.md#Java没有sizeof)
* [运算符总结](book/04-Operators.md#运算符总结)
* [本章小结](book/04-Operators.md#本章小结)
-## [第五章 控制流](book/05-Control-Flow.md)
+
+### [第五章 控制流](book/05-Control-Flow.md)
* [true和flase](book/05-Control-Flow.md#true和flase)
* [if-else](book/05-Control-Flow.md#if-else)
* [迭代语句](book/05-Control-Flow.md#迭代语句)
@@ -61,7 +69,8 @@
* [switch](book/05-Control-Flow.md#switch)
* [switch字符串](book/05-Control-Flow.md#switch字符串)
* [本章小结](book/05-Control-Flow.md#本章小结)
-## [第六章 初始化和清理](book/06-Housekeeping.md)
+
+### [第六章 初始化和清理](book/06-Housekeeping.md)
* [利用构造器保证初始化](book/06-Housekeeping.md#利用构造器保证初始化)
* [方法重载](book/06-Housekeeping.md#方法重载)
* [无参构造器](book/06-Housekeeping.md#无参构造器)
@@ -72,13 +81,15 @@
* [数组初始化](book/06-Housekeeping.md#数组初始化)
* [枚举类型](book/06-Housekeeping.md#枚举类型)
* [本章小结](book/06-Housekeeping.md#本章小结)
-## [第七章 封装](book/07-Implementation-Hiding.md)
+
+### [第七章 封装](book/07-Implementation-Hiding.md)
* [包的概念](book/07-Implementation-Hiding.md#包的概念)
* [访问权限修饰符](book/07-Implementation-Hiding.md#访问权限修饰符)
* [接口和实现](book/07-Implementation-Hiding.md#接口和实现)
* [类访问权限](book/07-Implementation-Hiding.md#类访问权限)
* [本章小结](book/07-Implementation-Hiding.md#本章小结)
-## [第八章 复用](book/08-Reuse.md)
+
+### [第八章 复用](book/08-Reuse.md)
* [组合语法](book/08-Reuse.md#组合语法)
* [继承语法](book/08-Reuse.md#继承语法)
* [委托](book/08-Reuse.md#委托)
@@ -89,14 +100,16 @@
* [final关键字](book/08-Reuse.md#final关键字)
* [类初始化和加载](book/08-Reuse.md#类初始化和加载)
* [本章小结](book/08-Reuse.md#本章小结)
-## [第九章 多态](book/09-Polymorphism.md)
+
+### [第九章 多态](book/09-Polymorphism.md)
* [向上转型回溯](book/09-Polymorphism.md#向上转型回溯)
* [深入理解](book/09-Polymorphism.md#深入理解)
* [构造器和多态](book/09-Polymorphism.md#构造器和多态)
* [返回类型协变](book/09-Polymorphism.md#返回类型协变)
* [使用继承设计](book/09-Polymorphism.md#使用继承设计)
* [本章小结](book/09-Polymorphism.md#本章小结)
-## [第十章 接口](book/10-Interfaces.md)
+
+### [第十章 接口](book/10-Interfaces.md)
* [抽象类和方法](book/10-Interfaces.md#抽象类和方法)
* [接口创建](book/10-Interfaces.md#接口创建)
* [抽象类和接口](book/10-Interfaces.md#抽象类和接口)
@@ -108,7 +121,8 @@
* [接口嵌套](book/10-Interfaces.md#接口嵌套)
* [接口和工厂方法模式](book/10-Interfaces.md#接口和工厂方法模式)
* [本章小结](book/10-Interfaces.md#本章小结)
-## [第十一章 内部类](book/11-Inner-Classes.md)
+
+### [第十一章 内部类](book/11-Inner-Classes.md)
* [创建内部类](book/11-Inner-Classes.md#创建内部类)
* [链接外部类](book/11-Inner-Classes.md#链接外部类)
* [内部类this和new的使用](book/11-Inner-Classes.md#内部类this和new的使用)
@@ -122,7 +136,8 @@
* [内部类局部变量](book/11-Inner-Classes.md#内部类局部变量)
* [内部类标识符](book/11-Inner-Classes.md#内部类标识符)
* [本章小结](book/11-Inner-Classes.md#本章小结)
-## [第十二章 集合](book/12-Collections.md)
+
+### [第十二章 集合](book/12-Collections.md)
* [泛型和类型安全的集合](book/12-Collections.md#泛型和类型安全的集合)
* [基本概念](book/12-Collections.md#基本概念)
* [添加元素组](book/12-Collections.md#添加元素组)
@@ -137,7 +152,8 @@
* [集合与迭代器](book/12-Collections.md#集合与迭代器)
* [for-in和迭代器](book/12-Collections.md#for-in和迭代器)
* [本章小结](book/12-Collections.md#本章小结)
-## [第十三章 函数式编程](book/13-Functional-Programming.md)
+
+### [第十三章 函数式编程](book/13-Functional-Programming.md)
* [新旧对比](book/13-Functional-Programming.md#新旧对比)
* [Lambda表达式](book/13-Functional-Programming.md#Lambda表达式)
* [方法引用](book/13-Functional-Programming.md#方法引用)
@@ -148,14 +164,16 @@
* [柯里化和部分求值](book/13-Functional-Programming.md#柯里化和部分求值)
* [纯函数式编程](book/13-Functional-Programming.md#纯函数式编程)
* [本章小结](book/13-Functional-Programming.md#本章小结)
-## [第十四章 流式编程](book/14-Streams.md)
+
+### [第十四章 流式编程](book/14-Streams.md)
* [流支持](book/14-Streams.md#流支持)
* [流创建](book/14-Streams.md#流创建)
* [中级流操作](book/14-Streams.md#中级流操作)
* [Optional类](book/14-Streams.md#Optional类)
* [终端操作](book/14-Streams.md#终端操作)
* [本章小结](book/14-Streams.md#本章小结)
-## [第十五章 异常](book/15-Exceptions.md)
+
+### [第十五章 异常](book/15-Exceptions.md)
* [异常概念](book/15-Exceptions.md#异常概念)
* [基本异常](book/15-Exceptions.md#基本异常)
* [异常捕获](book/15-Exceptions.md#异常捕获)
@@ -171,7 +189,8 @@
* [异常准则](book/15-Exceptions.md#异常准则)
* [异常指南](book/15-Exceptions.md#异常指南)
* [本章小结](book/15-Exceptions.md#本章小结)
-## [第十六章 代码校验](book/16-Validating-Your-Code.md)
+
+### [第十六章 代码校验](book/16-Validating-Your-Code.md)
* [测试](book/16-Validating-Your-Code.md#测试)
* [前提条件](book/16-Validating-Your-Code.md#前提条件)
* [测试驱动开发](book/16-Validating-Your-Code.md#测试驱动开发)
@@ -186,7 +205,8 @@
* [重构](book/16-Validating-Your-Code.md#重构)
* [持续集成](book/16-Validating-Your-Code.md#持续集成)
* [本章小结](book/16-Validating-Your-Code.md#本章小结)
-## [第十七章 文件](book/17-Files.md)
+
+### [第十七章 文件](book/17-Files.md)
* [文件和目录路径](book/17-Files.md#文件和目录路径)
* [目录](book/17-Files.md#目录)
* [文件系统](book/17-Files.md#文件系统)
@@ -194,7 +214,8 @@
* [文件查找](book/17-Files.md#文件查找)
* [文件读写](book/17-Files.md#文件读写)
* [本章小结](book/17-Files.md#本章小结)
-## [第十八章 字符串](book/18-Strings.md)
+
+### [第十八章 字符串](book/18-Strings.md)
* [字符串的不可变](book/18-Strings.md#字符串的不可变)
* [重载和StringBuilder](book/18-Strings.md#重载和StringBuilder)
* [意外递归](book/18-Strings.md#意外递归)
@@ -204,7 +225,8 @@
* [扫描输入](book/18-Strings.md#扫描输入)
* [StringTokenizer类](book/18-Strings.md#StringTokenizer类)
* [本章小结](book/18-Strings.md#本章小结)
-## [第十九章 类型信息](book/19-Type-Information.md)
+
+### [第十九章 类型信息](book/19-Type-Information.md)
* [运行时类型信息](book/19-Type-Information.md#运行时类型信息)
* [类的对象](book/19-Type-Information.md#类的对象)
* [类型转换检测](book/19-Type-Information.md#类型转换检测)
@@ -215,7 +237,8 @@
* [Optional类](book/19-Type-Information.md#Optional类)
* [接口和类型](book/19-Type-Information.md#接口和类型)
* [本章小结](book/19-Type-Information.md#本章小结)
-## [第二十章 泛型](book/20-Generics.md)
+
+### [第二十章 泛型](book/20-Generics.md)
* [简单泛型](book/20-Generics.md#简单泛型)
* [泛型接口](book/20-Generics.md#泛型接口)
* [泛型方法](book/20-Generics.md#泛型方法)
@@ -233,7 +256,8 @@
* [补偿不足](book/20-Generics.md#补偿不足)
* [辅助潜在类型](book/20-Generics.md#辅助潜在类型)
* [泛型的优劣](book/20-Generics.md#泛型的优劣)
-## [第二十一章 数组](book/21-Arrays.md)
+
+### [第二十一章 数组](book/21-Arrays.md)
* [数组特性](book/21-Arrays.md#数组特性)
* [一等对象](book/21-Arrays.md#一等对象)
* [返回数组](book/21-Arrays.md#返回数组)
@@ -254,7 +278,8 @@
* [binarySearch二分查找](book/21-Arrays.md#binarySearch二分查找)
* [parallelPrefix并行前缀](book/21-Arrays.md#parallelPrefix并行前缀)
* [本章小结](book/21-Arrays.md#本章小结)
-## [第二十二章 枚举](book/22-Enumerations.md)
+
+### [第二十二章 枚举](book/22-Enumerations.md)
* [基本功能](book/22-Enumerations.md#基本功能)
* [方法添加](book/22-Enumerations.md#方法添加)
* [switch语句](book/22-Enumerations.md#switch语句)
@@ -267,13 +292,15 @@
* [常量特定方法](book/22-Enumerations.md#常量特定方法)
* [多次调度](book/22-Enumerations.md#多次调度)
* [本章小结](book/22-Enumerations.md#本章小结)
-## [第二十三章 注解](book/23-Annotations.md)
+
+### [第二十三章 注解](book/23-Annotations.md)
* [基本语法](book/23-Annotations.md#基本语法)
* [编写注解处理器](book/23-Annotations.md#编写注解处理器)
* [使用javac处理注解](book/23-Annotations.md#使用javac处理注解)
* [基于注解的单元测试](book/23-Annotations.md#基于注解的单元测试)
* [本章小结](book/23-Annotations.md#本章小结)
-## [第二十四章 并发编程](book/24-Concurrent-Programming.md)
+
+### [第二十四章 并发编程](book/24-Concurrent-Programming.md)
* [术语问题](book/24-Concurrent-Programming.md#术语问题)
* [并发的超能力](book/24-Concurrent-Programming.md#并发的超能力)
* [针对速度](book/24-Concurrent-Programming.md#针对速度)
@@ -288,7 +315,8 @@
* [构造函数非线程安全](book/24-Concurrent-Programming.md#构造函数非线程安全)
* [复杂性和代价](book/24-Concurrent-Programming.md#复杂性和代价)
* [本章小结](book/24-Concurrent-Programming.md#本章小结)
-## [第二十五章 设计模式](book/25-Patterns.md)
+
+### [第二十五章 设计模式](book/25-Patterns.md)
* [概念](book/25-Patterns.md#概念)
* [构建型](book/25-Patterns.md#构建型)
* [面向实施](book/25-Patterns.md#面向实施)
@@ -305,21 +333,25 @@
* [RTTI的优劣](book/25-Patterns.md#RTTI的优劣)
* [本章小结](book/25-Patterns.md#本章小结)
-## [附录:补充](book/Appendix-Supplements.md)
+### [附录:补充](book/Appendix-Supplements.md)
* [可下载的补充](book/Appendix-Supplements.md#可下载的补充)
* [通过Thinking-in-C来巩固Java基础](book/Appendix-Supplements.md#通过Thinking-in-C来巩固Java基础)
* [动手实践](book/Appendix-Supplements.md#动手实践)
-## [附录:编程指南](book/Appendix-Programming-Guidelines.md)
+
+### [附录:编程指南](book/Appendix-Programming-Guidelines.md)
* [设计](book/Appendix-Programming-Guidelines.md#设计)
* [实现](book/Appendix-Programming-Guidelines.md#实现)
-## [附录:文档注释](book/Appendix-Javadoc.md)
-## [附录:对象传递和返回](book/Appendix-Passing-and-Returning-Objects.md)
+
+### [附录:文档注释](book/Appendix-Javadoc.md)
+
+### [附录:对象传递和返回](book/Appendix-Passing-and-Returning-Objects.md)
* [传递引用](book/Appendix-Passing-and-Returning-Objects.md#传递引用)
* [本地拷贝](book/Appendix-Passing-and-Returning-Objects.md#本地拷贝)
* [控制克隆](book/Appendix-Passing-and-Returning-Objects.md#控制克隆)
* [不可变类](book/Appendix-Passing-and-Returning-Objects.md#不可变类)
* [本章小结](book/Appendix-Passing-and-Returning-Objects.md#本章小结)
-## [附录:流式IO](book/Appendix-IO-Streams.md)
+
+### [附录:流式IO](book/Appendix-IO-Streams.md)
* [输入流类型](book/Appendix-IO-Streams.md#输入流类型)
* [输出流类型](book/Appendix-IO-Streams.md#输出流类型)
* [添加属性和有用的接口](book/Appendix-IO-Streams.md#添加属性和有用的接口)
@@ -327,9 +359,11 @@
* [RandomAccessFile类](book/Appendix-IO-Streams.md#RandomAccessFile类)
* [IO流典型用途](book/Appendix-IO-Streams.md#IO流典型用途)
* [本章小结](book/Appendix-IO-Streams.md#本章小结)
-## [附录:标准IO](book/Appendix-Standard-IO.md)
+
+### [附录:标准IO](book/Appendix-Standard-IO.md)
* [执行控制](book/Appendix-Standard-IO.md#执行控制)
-## [附录:新IO](book/Appendix-New-IO.md)
+
+### [附录:新IO](book/Appendix-New-IO.md)
* [ByteBuffer](book/Appendix-New-IO.md#ByteBuffer)
* [转换数据](book/Appendix-New-IO.md#数据转换)
* [获取原始类型](book/Appendix-New-IO.md#基本类型获取)
@@ -337,11 +371,13 @@
* [使用缓冲区进行数据操作](book/Appendix-New-IO.md#缓冲区数据操作)
* [内存映射文件](book/Appendix-New-IO.md#内存映射文件)
* [文件锁定](book/Appendix-New-IO.md#文件锁定)
-## [附录:理解equals和hashCode方法](book/Appendix-Understanding-equals-and-hashCode.md)
+
+### [附录:理解equals和hashCode方法](book/Appendix-Understanding-equals-and-hashCode.md)
* [equals典范](book/Appendix-Understanding-equals-and-hashCode.md#equals典范)
* [哈希和哈希码](book/Appendix-Understanding-equals-and-hashCode.md#哈希和哈希码)
* [调整HashMap](book/Appendix-Understanding-equals-and-hashCode.md#调整HashMap)
-## [附录:集合主题](book/Appendix-Collection-Topics.md)
+
+### [附录:集合主题](book/Appendix-Collection-Topics.md)
* [示例数据](book/Appendix-Collection-Topics.md#示例数据)
* [List表现](book/Appendix-Collection-Topics.md#List表现)
* [Set表现](book/Appendix-Collection-Topics.md#Set表现)
@@ -358,7 +394,8 @@
* [持有引用](book/Appendix-Collection-Topics.md#持有引用)
* [避免旧式类库](book/Appendix-Collection-Topics.md#避免旧式类库)
* [本章小结](book/Appendix-Collection-Topics.md#本章小结)
-## [附录:并发底层原理](book/Appendix-Low-Level-Concurrency.md)
+
+### [附录:并发底层原理](book/Appendix-Low-Level-Concurrency.md)
* [线程](book/Appendix-Low-Level-Concurrency.md#线程)
* [异常捕获](book/Appendix-Low-Level-Concurrency.md#异常捕获)
* [资源共享](book/Appendix-Low-Level-Concurrency.md#资源共享)
@@ -367,26 +404,32 @@
* [关键部分](book/Appendix-Low-Level-Concurrency.md#关键部分)
* [库组件](book/Appendix-Low-Level-Concurrency.md#库组件)
* [本章小结](book/Appendix-Low-Level-Concurrency.md#本章小结)
-## [附录:数据压缩](book/Appendix-Data-Compression.md)
+
+### [附录:数据压缩](book/Appendix-Data-Compression.md)
* [使用Gzip简单压缩](book/Appendix-Data-Compression.md#使用Gzip简单压缩)
* [使用zip多文件存储](book/Appendix-Data-Compression.md#使用zip多文件存储)
* [Java的jar](book/Appendix-Data-Compression.md#Java的jar)
-## [附录:对象序列化](book/Appendix-Object-Serialization.md)
+
+### [附录:对象序列化](book/Appendix-Object-Serialization.md)
* [查找类](book/Appendix-Object-Serialization.md#查找类)
* [控制序列化](book/Appendix-Object-Serialization.md#控制序列化)
* [使用持久化](book/Appendix-Object-Serialization.md#使用持久化)
-## [附录:静态语言类型检查](book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md)
+
+### [附录:静态语言类型检查](book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md)
* [前言](book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md#前言)
* [静态类型检查和测试](book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md#静态类型检查和测试)
* [如何提升打字](book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md#如何提升打字)
* [生产力的成本](book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md#生产力的成本)
* [静态和动态](book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md#静态和动态)
-## [附录:C++和Java的优良传统](book/Appendix-The-Positive-Legacy-of-C-plus-plus-and-Java.md)
-## [附录:成为一名程序员](book/Appendix-Becoming-a-Programmer.md)
+
+### [附录:C++和Java的优良传统](book/Appendix-The-Positive-Legacy-of-C-plus-plus-and-Java.md)
+
+### [附录:成为一名程序员](book/Appendix-Becoming-a-Programmer.md)
* [如何开始](book/Appendix-Becoming-a-Programmer.md#如何开始)
* [码农生涯](book/Appendix-Becoming-a-Programmer.md#码农生涯)
* [百分之五的神话](book/Appendix-Becoming-a-Programmer.md#百分之五的神话)
* [重在动手](book/Appendix-Becoming-a-Programmer.md#重在动手)
* [像打字般编程](book/Appendix-Becoming-a-Programmer.md#像打字般编程)
* [做你喜欢的事](book/Appendix-Becoming-a-Programmer.md#做你喜欢的事)
-## [词汇表](book/GLOSSARY.md)
+
+### [词汇表](book/GLOSSARY.md)
From b393994e298146d85714762cb96d34c7e7b9a3bf Mon Sep 17 00:00:00 2001
From: Lane
Date: Mon, 14 Sep 2020 16:06:40 +0800
Subject: [PATCH 07/68] =?UTF-8?q?=E7=9B=AE=E5=BD=95=E5=92=8C=E6=AD=A3?=
=?UTF-8?q?=E6=96=87=E7=9B=B8=E5=AF=B9=E5=BA=94=E4=BB=A5=E4=BE=BF=E8=B7=B3?=
=?UTF-8?q?=E8=BD=AC=20(#575)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
`中级流操作` => `中间操作`
---
docs/sidebar.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/sidebar.md b/docs/sidebar.md
index e79c07a0..dbde9004 100644
--- a/docs/sidebar.md
+++ b/docs/sidebar.md
@@ -168,7 +168,7 @@
### [第十四章 流式编程](book/14-Streams.md)
* [流支持](book/14-Streams.md#流支持)
* [流创建](book/14-Streams.md#流创建)
- * [中级流操作](book/14-Streams.md#中级流操作)
+ * [中间操作](book/14-Streams.md#中间操作)
* [Optional类](book/14-Streams.md#Optional类)
* [终端操作](book/14-Streams.md#终端操作)
* [本章小结](book/14-Streams.md#本章小结)
From 897c0affba7d211378177a7e6dac6d53106c5737 Mon Sep 17 00:00:00 2001
From: FengBaoheng
Date: Mon, 14 Sep 2020 17:17:48 +0800
Subject: [PATCH 08/68] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E9=83=A8=E5=88=86?=
=?UTF-8?q?=E9=94=99=E5=88=AB=E5=AD=97=E5=92=8C=E8=AF=AD=E5=BA=8F=20(#576)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* fix typo 本章小节->本章小结
* fix typos on 20-Generics
修正20章的打字错误
* 添加示例代码链接
* 修改了部分错别字,调整语序
---
docs/book/23-Annotations.md | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/docs/book/23-Annotations.md b/docs/book/23-Annotations.md
index 95b79088..1b585691 100644
--- a/docs/book/23-Annotations.md
+++ b/docs/book/23-Annotations.md
@@ -16,7 +16,7 @@
- **@Deprecated**:如果使用该注解的元素被调用,编译器就会发出警告信息。
- **@SuppressWarnings**:关闭不当的编译器警告信息。
- **@SafeVarargs**:在 Java 7 中加入用于禁止对具有泛型varargs参数的方法或构造函数的调用方发出警告。
-- **@FunctionalInterface**:Java 8 中加入用于表示类型声明为函数式接口
+- **@FunctionalInterface**:Java 8 中加入用于表示类型声明为函数式接口。
还有 5 种额外的注解类型用于创造新的注解。你将会在这一章学习它们。
@@ -45,7 +45,7 @@ public class Testable {
}
```
-被注解标注的方法和其他的方法没有任何区别。在这个例子中,注解 `@Test` 可以和任何修饰符共同用于方法,诸如 **public**、**static** 或 **void**。从语法的角度上看,注解的使用方式和修饰符的使用方式一致。
+被注解标注的方法和其他方法没有任何区别。在这个例子中,注解 `@Test` 可以和任何修饰符共同用于方法,诸如 **public**、**static** 或 **void**。从语法的角度上看,注解和修饰符的使用方式是一致的。
### 定义注解
@@ -61,7 +61,7 @@ import java.lang.annotation.*;
public @interface Test {}
```
-除了 @ 符号之外, `@Test` 的定义看起来更像一个空接口。注解的定义也需要一些元注解(meta-annoation),比如 `@Target` 和 `@Retention`。`@Target` 定义你的注解可以应用在哪里(例如是方法还是字段)。`@Retention` 定义了注解在哪里可用,在源代码中(SOURCE),class文件(CLASS)中或者是在运行时(RUNTIME)。
+除了 @ 符号之外, `@Test` 的定义看起来更像一个空接口。注解的定义也需要一些元注解(meta-annotation),比如 `@Target` 和 `@Retention`。`@Target` 定义你的注解可以应用在哪里(例如是方法还是字段)。`@Retention` 定义了注解在哪里可用,在源代码中(SOURCE),class文件(CLASS)中或者是在运行时(RUNTIME)。
注解通常会包含一些表示特定值的元素。当分析处理注解的时候,程序或工具可以利用这些值。注解的元素看起来就像接口的方法,但是可以为其指定默认值。
@@ -206,7 +206,7 @@ public @interface SimulatingNull {
### 生成外部文件
-当有些框架需要一些额外的信息才能与你的源代码协同工作,这种情况下注解就会变得十分有用。像 Enterprise JavaBeans (EJB3 之前)这样的技术,每一个 Bean 都需要需要大量的接口和部署描述文件,而这些就是“样板”文件。Web Service,自定义标签库以及对象/关系映射工具(例如 Toplink 和 Hibernate)通常都需要 XML 描述文件,而这些文件脱离于代码之外。除了定义 Java 类,程序员还必须忍受沉闷,重复的提供某些信息,例如类名和包名等已经在原始类中已经提供的信息。每当你使用外部描述文件时,他就拥有了一个类的两个独立信息源,这经常导致代码的同步问题。同时这也要求了为项目工作的程序员在知道如何编写 Java 程序的同时,也必须知道如何编辑描述文件。
+当有些框架需要一些额外的信息才能与你的源代码协同工作,这种情况下注解就会变得十分有用。像 Enterprise JavaBeans (EJB3 之前)这样的技术,每一个 Bean 都需要大量的接口和部署描述文件,而这些就是“样板”文件。Web Service,自定义标签库以及对象/关系映射工具(例如 Toplink 和 Hibernate)通常都需要 XML 描述文件,而这些文件脱离于代码之外。除了定义 Java 类,程序员还必须忍受沉闷,重复的提供某些信息,例如类名和包名等已经在原始类中提供过的信息。每当你使用外部描述文件时,他就拥有了一个类的两个独立信息源,这经常导致代码的同步问题。同时这也要求了为项目工作的程序员在知道如何编写 Java 程序的同时,也必须知道如何编辑描述文件。
假设你想提供一些基本的对象/关系映射功能,能够自动生成数据库表。你可以使用 XML 描述文件来指明类的名字、每个成员以及数据库映射的相关信息。但是,通过使用注解,你可以把所有信息都保存在 **JavaBean** 源文件中。为此你需要一些用于定义数据库表名称、数据库列以及将 SQL 类型映射到属性的注解。
@@ -306,7 +306,7 @@ public class Member {
}
```
-类注解 **@DBTable** 注解给定了元素值 MEMBER,它将会作为标的名字。类的属性 **firstName** 和 **lastName** 都被注解为 **@SQLString** 类型并且给了默认元素值分别为 30 和 50。这些注解都有两个有趣的地方:首先,他们都使用了嵌入的 **@Constraints** 注解的默认值;其次,它们都是用了快捷方式特性。如果你在注解中定义了名为 **value** 的元素,并且在使用该注解时,**value** 为唯一一个需要赋值的元素,你就不需要使用名—值对的语法,你只需要在括号中给出 **value** 元素的值即可。这可以应用于任何合法类型的元素。这也限制了你必须将元素命名为 **value**,不过在上面的例子中,这样的注解语句也更易于理解:
+类注解 **@DBTable** 注解给定了元素值 MEMBER,它将会作为表的名字。类的属性 **firstName** 和 **lastName** 都被注解为 **@SQLString** 类型并且给了默认元素值分别为 30 和 50。这些注解都有两个有趣的地方:首先,他们都使用了嵌入的 **@Constraints** 注解的默认值;其次,它们都是用了快捷方式特性。如果你在注解中定义了名为 **value** 的元素,并且在使用该注解时,**value** 为唯一一个需要赋值的元素,你就不需要使用名—值对的语法,你只需要在括号中给出 **value** 元素的值即可。这可以应用于任何合法类型的元素。这也限制了你必须将元素命名为 **value**,不过在上面的例子中,这样的注解语句也更易于理解:
```java
@SQLString(30)
@@ -320,7 +320,7 @@ public class Member {
可以使用多种不同的方式来定义自己的注解用于上述任务。例如,你可以使用一个单一的注解类 **@TableColumn**,它拥有一个 **enum** 元素,元素值定义了 **STRING**,**INTEGER**,**FLOAT** 等类型。这消除了每个 SQL 类型都需要定义一个 **@interface** 的负担,不过也使得用额外信息修饰 SQL 类型变的不可能,这些额外的信息例如长度或精度等,都可能是非常有用的。
-你也可以使用一个 **String** 类型的元素来描述实际的 SQL 类型,比如 “VARCHAR(30)” 或者 “INTEGER”。这使得你可以修饰 SQL 类型,但是这也将 Java 类型到 SQL 类型的映射绑在了一起,这不是一个好的设计。你并不想在数据库更改之后重新编译你的代码;如果我们只需要告诉注解处理器,我们正在使用的是什么“口味(favor)”的 SQL,然后注解助力器来为我们处理 SQL 类型的细节,那将是一个优雅的设计。
+你也可以使用一个 **String** 类型的元素来描述实际的 SQL 类型,比如 “VARCHAR(30)” 或者 “INTEGER”。这使得你可以修饰 SQL 类型,但是这也将 Java 类型到 SQL 类型的映射绑在了一起,这不是一个好的设计。你并不想在数据库更改之后重新编译你的代码;如果我们只需要告诉注解处理器,我们正在使用的是什么“口味(favor)”的 SQL,然后注解处理器来为我们处理 SQL 类型的细节,那将是一个优雅的设计。
第三种可行的方案是一起使用两个注解,**@Constraints** 和相应的 SQL 类型(例如,**@SQLInteger**)去注解同一个字段。这可能会让代码有些混乱,但是编译器允许你对同一个目标使用多个注解。在 Java 8,在使用多个注解的时候,你可以重复使用同一个注解。
@@ -459,7 +459,7 @@ CREATE TABLE MEMBER(
每一个你编写的注解都需要处理器,但是 **javac** 可以非常容易的将多个注解处理器合并在一起。你可以指定多个需要处理的类,并且你可以添加监听器用于监听注解处理完成后接到通知。
-本节中的示例将帮助你开始学习,但如果你必须深入学习,请做好反复学习,大量访问 Google 和StackOverflow 的准备。
+本节中的示例将帮助你开始学习,但如果你必须深入学习,请做好反复学习,大量访问 Google 和 StackOverflow 的准备。
### 最简单的处理器
@@ -576,11 +576,11 @@ public class SimpleProcessor
}
```
-(旧的,失效的)**apt** 版本的处理器需要额外的方法来确定支持哪些注解以及支持的 Java 版本。不过,你现在可以简单的使用 **@SupportedAnnotationTypes** 和 **@SupportedSourceVersion** 注解(这是一个很好的示例关于注解如何简化你的代码)。
+(旧的,失效的)**apt** 版本的处理器需要额外的方法来确定支持哪些注解以及支持的 Java 版本。不过,你现在可以简单的使用 **@SupportedAnnotationTypes** 和 **@SupportedSourceVersion** 注解(这是一个很好的用注解简化代码的示例)。
-你唯一需要实现的方法就是 `process()`,这里是所有行为发生的地方。第一个参数告诉你哪个注解是存在的,第二个参数保留了剩余信息。我们所做的事情只是打印了注解(这里只存在一个),可以看 **TypeElement** 文档中的其他行为。通过使用 `process()` 的第二个操作,我们循环所有被 **@Simple** 注解的元素,并且针对每一个元素调用我们的 `display()` 方法。所有 **Element** 展示了本身的基本信息;例如,`getModifiers()` 告诉你它是否为 **public** 和 **static** 的。
+你唯一需要实现的方法就是 `process()`,这里是所有行为发生的地方。第一个参数告诉你哪个注解是存在的,第二个参数保留了剩余信息。我们所做的事情只是打印了注解(这里只存在一个),可以看 **TypeElement** 文档中的其他行为。通过使用 `process()` 的第二个操作,我们循环所有被 **@Simple** 注解的元素,并且针对每一个元素调用我们的 `display()` 方法。所有 **Element** 展示了自身的基本信息;例如,`getModifiers()` 告诉你它是否为 **public** 和 **static** 。
-**Element** 只能执行那些编译器解析的所有基本对象共有的操作,而类和方法之类的东西有额外的信息需要提取。所以(如果你阅读了正确的文档,但是我没有在任何文档中找到——我不得不通过 StackOverflow 寻找线索)你检查它是哪种 **ElementKind**,然后将其向下转换为更具体的元素类型,注入针对 CLASS 的 TypeElement 和 针对 METHOD 的ExecutableElement。此时,可以为这些元素调用其他方法。
+**Element** 只能执行那些编译器解析的所有基本对象共有的操作,而类和方法之类的东西有额外的信息需要提取。所以(如果你阅读了正确的文档,但是我没有在任何文档中找到——我不得不通过 StackOverflow 寻找线索)你检查它是哪种 **ElementKind**,然后将其向下转换为更具体的元素类型,注入针对 CLASS 的 TypeElement 和针对 METHOD 的ExecutableElement。此时,可以为这些元素调用其他方法。
动态向下转型(在编译期不进行检查)并不像是 Java 的做事方式,这非常不直观这也是为什么我从未想过要这样做事。相反,我花了好几天的时间,试图发现你应该如何访问这些信息,而这些信息至少在某种程度上是用不起作用的恰当方法简单明了的。我还没有遇到任何东西说上面是规范的形式,但在我看来是。
From cd32cda6ae05d325051a4c3fa3dfff63014d4a19 Mon Sep 17 00:00:00 2001
From: Hongkuan Wang
Date: Tue, 15 Sep 2020 05:42:14 +0300
Subject: [PATCH 09/68] Fix typo (#578)
---
docs/book/Appendix-Understanding-equals-and-hashCode.md | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/docs/book/Appendix-Understanding-equals-and-hashCode.md b/docs/book/Appendix-Understanding-equals-and-hashCode.md
index 9cfeb1d5..01889642 100644
--- a/docs/book/Appendix-Understanding-equals-and-hashCode.md
+++ b/docs/book/Appendix-Understanding-equals-and-hashCode.md
@@ -69,7 +69,8 @@ import java.util.*;
public class Equality {
protected int i;
protected String s;
- protected double d;public Equality(int i, String s, double d) {
+ protected double d;
+ public Equality(int i, String s, double d) {
this.i = i;
this.s = s;
this.d = d;
@@ -141,7 +142,7 @@ Expected false, got false
**testAll()** 执行了我们期望的所有不同类型对象的比较。它使用工厂创建了**Equality**对象。
-在 **main()** 里,请注意对 **testAll()** 的调用很简单。因为**EqualityFactory**有着单一的函数,它能够和lambda表达式一起使用来表示**make()**函数。
+在 **main()** 里,请注意对 **testAll()** 的调用很简单。因为**EqualityFactory**有着单一的函数,它能够和lambda表达式一起使用来表示 **make()** 函数。
上述的 **equals()** 函数非常繁琐,并且我们能够将其简化成规范的形式,请注意:
1. **instanceof**检查减少了**null**检查的需要。
From 44a3892ec6397e5030bace80933eec9b516589a3 Mon Sep 17 00:00:00 2001
From: Lane
Date: Tue, 15 Sep 2020 10:58:46 +0800
Subject: [PATCH 10/68] rebuild sidebar.md and SUMMARY.md (#580)
---
SUMMARY.md | 860 +++++++++++++------------
docs/book/05-Control-Flow.md | 2 +-
docs/book/11-Inner-Classes.md | 0
docs/book/18-Strings.md | 2 +-
docs/book/19-Type-Information.md | 2 +-
docs/book/21-Arrays.md | 2 +-
docs/book/24-Concurrent-Programming.md | 2 +-
docs/book/Appendix-Standard-IO.md | 2 +-
docs/index.html | 32 +-
docs/sidebar.md | 249 +++----
10 files changed, 600 insertions(+), 553 deletions(-)
mode change 100644 => 100755 docs/book/05-Control-Flow.md
mode change 100644 => 100755 docs/book/11-Inner-Classes.md
mode change 100644 => 100755 docs/book/18-Strings.md
mode change 100644 => 100755 docs/book/19-Type-Information.md
mode change 100644 => 100755 docs/book/21-Arrays.md
mode change 100644 => 100755 docs/book/24-Concurrent-Programming.md
mode change 100644 => 100755 docs/book/Appendix-Standard-IO.md
mode change 100644 => 100755 docs/index.html
diff --git a/SUMMARY.md b/SUMMARY.md
index a15b48fc..5f2b8733 100644
--- a/SUMMARY.md
+++ b/SUMMARY.md
@@ -1,414 +1,448 @@
-# Summary
-
-* [Introduction](README.md)
-* [译者的话](docs/README.md)
-* [封面](docs/book/00-On-Java-8.md)
-* [前言](docs/book/00-Preface.md)
- * [教学目标](docs/book/00-Preface.md#教学目标)
- * [语言设计错误](docs/book/00-Preface.md#语言设计错误)
- * [测试用例](docs/book/00-Preface.md#测试用例)
- * [普及性](docs/book/00-Preface.md#普及性)
- * [关于安卓](docs/book/00-Preface.md#关于安卓)
- * [电子版权声明](docs/book/00-Preface.md#电子版权声明)
- * [版本说明](docs/book/00-Preface.md#版本说明)
- * [封面设计](docs/book/00-Preface.md#封面设计)
- * [感谢的人](docs/book/00-Preface.md#感谢的人)
- * [献礼](docs/book/00-Preface.md#献礼)
-* [简介](docs/book/00-Introduction.md)
- * [前提条件](docs/book/00-Introduction.md#前提条件)
- * [JDK文档](docs/book/00-Introduction.md#JDK文档)
- * [C编程思想](docs/book/00-Introduction.md#C编程思想)
- * [源码下载](docs/book/00-Introduction.md#源码下载)
- * [编码样式](docs/book/00-Introduction.md#编码样式)
- * [BUG提交](docs/book/00-Introduction.md#BUG提交)
- * [邮箱订阅](docs/book/00-Introduction.md#邮箱订阅)
- * [Java图形界面](docs/book/00-Introduction.md#Java图形界面)
-
-* [第一章 对象的概念](docs/book/01-What-is-an-Object.md)
- * [抽象](docs/book/01-What-is-an-Object.md#抽象)
- * [接口](docs/book/01-What-is-an-Object.md#接口)
- * [服务提供](docs/book/01-What-is-an-Object.md#服务提供)
- * [封装](docs/book/01-What-is-an-Object.md#封装)
- * [复用](docs/book/01-What-is-an-Object.md#复用)
- * [继承](docs/book/01-What-is-an-Object.md#继承)
- * [多态](docs/book/01-What-is-an-Object.md#多态)
- * [单继承](docs/book/01-What-is-an-Object.md#单继承)
- * [集合](docs/book/01-What-is-an-Object.md#集合)
- * [生命周期](docs/book/01-What-is-an-Object.md#生命周期)
- * [异常处理](docs/book/01-What-is-an-Object.md#异常处理)
- * [本章小结](docs/book/01-What-is-an-Object.md#本章小结)
-* [第二章 安装Java和本书用例](docs/book/02-Installing-Java-and-the-Book-Examples.md)
- * [编辑器](docs/book/02-Installing-Java-and-the-Book-Examples.md#编辑器)
- * [Shell](docs/book/02-Installing-Java-and-the-Book-Examples.md#Shell)
- * [Java安装](docs/book/02-Installing-Java-and-the-Book-Examples.md#Java安装)
- * [校验安装](docs/book/02-Installing-Java-and-the-Book-Examples.md#校验安装)
- * [安装和运行代码示例](docs/book/02-Installing-Java-and-the-Book-Examples.md#安装和运行代码示例)
-* [第三章 万物皆对象](docs/book/03-Objects-Everywhere.md)
- * [对象操纵](docs/book/03-Objects-Everywhere.md#对象操纵)
- * [对象创建](docs/book/03-Objects-Everywhere.md#对象创建)
- * [代码注释](docs/book/03-Objects-Everywhere.md#代码注释)
- * [对象清理](docs/book/03-Objects-Everywhere.md#对象清理)
- * [类的创建](docs/book/03-Objects-Everywhere.md#类的创建)
- * [程序编写](docs/book/03-Objects-Everywhere.md#程序编写)
- * [小试牛刀](docs/book/03-Objects-Everywhere.md#小试牛刀)
- * [编码风格](docs/book/03-Objects-Everywhere.md#编码风格)
- * [本章小结](docs/book/03-Objects-Everywhere.md#本章小结)
-* [第四章 运算符](docs/book/04-Operators.md)
- * [使用说明](docs/book/04-Operators.md#使用说明)
- * [优先级](docs/book/04-Operators.md#优先级)
- * [赋值](docs/book/04-Operators.md#赋值)
- * [算术运算符](docs/book/04-Operators.md#算术运算符)
- * [递增和递减](docs/book/04-Operators.md#递增和递减)
- * [关系运算符](docs/book/04-Operators.md#关系运算符)
- * [逻辑运算符](docs/book/04-Operators.md#逻辑运算符)
- * [字面值常量](docs/book/04-Operators.md#字面值常量)
- * [按位运算符](docs/book/04-Operators.md#按位运算符)
- * [移位运算符](docs/book/04-Operators.md#移位运算符)
- * [三元运算符](docs/book/04-Operators.md#三元运算符)
- * [字符串运算符](docs/book/04-Operators.md#字符串运算符)
- * [常见陷阱](docs/book/04-Operators.md#常见陷阱)
- * [类型转换](docs/book/04-Operators.md#类型转换)
- * [Java没有sizeof](docs/book/04-Operators.md#Java没有sizeof)
- * [运算符总结](docs/book/04-Operators.md#运算符总结)
- * [本章小结](docs/book/04-Operators.md#本章小结)
-* [第五章 控制流](docs/book/05-Control-Flow.md)
- * [true和false](docs/book/05-Control-Flow.md#true和false)
- * [if-else](docs/book/05-Control-Flow.md#if-else)
- * [迭代语句](docs/book/05-Control-Flow.md#迭代语句)
- * [for-in语法](docs/book/05-Control-Flow.md#for-in语法)
- * [return](docs/book/05-Control-Flow.md#return)
- * [break和continue](docs/book/05-Control-Flow.md#break和continue)
- * [臭名昭著的goto](docs/book/05-Control-Flow.md#臭名昭著的goto)
- * [switch](docs/book/05-Control-Flow.md#switch)
- * [switch字符串](docs/book/05-Control-Flow.md#switch字符串)
- * [本章小结](docs/book/05-Control-Flow.md#本章小结)
-* [第六章 初始化和清理](docs/book/06-Housekeeping.md)
- * [利用构造器保证初始化](docs/book/06-Housekeeping.md#利用构造器保证初始化)
- * [方法重载](docs/book/06-Housekeeping.md#方法重载)
- * [无参构造器](docs/book/06-Housekeeping.md#无参构造器)
- * [this关键字](docs/book/06-Housekeeping.md#this关键字)
- * [垃圾回收器](docs/book/06-Housekeeping.md#垃圾回收器)
- * [成员初始化](docs/book/06-Housekeeping.md#成员初始化)
- * [构造器初始化](docs/book/06-Housekeeping.md#构造器初始化)
- * [数组初始化](docs/book/06-Housekeeping.md#数组初始化)
- * [枚举类型](docs/book/06-Housekeeping.md#枚举类型)
- * [本章小结](docs/book/06-Housekeeping.md#本章小结)
-* [第七章 封装](docs/book/07-Implementation-Hiding.md)
- * [包的概念](docs/book/07-Implementation-Hiding.md#包的概念)
- * [访问权限修饰符](docs/book/07-Implementation-Hiding.md#访问权限修饰符)
- * [接口和实现](docs/book/07-Implementation-Hiding.md#接口和实现)
- * [类访问权限](docs/book/07-Implementation-Hiding.md#类访问权限)
- * [本章小结](docs/book/07-Implementation-Hiding.md#本章小结)
-* [第八章 复用](docs/book/08-Reuse.md)
- * [组合语法](docs/book/08-Reuse.md#组合语法)
- * [继承语法](docs/book/08-Reuse.md#继承语法)
- * [委托](docs/book/08-Reuse.md#委托)
- * [结合组合与继承](docs/book/08-Reuse.md#结合组合与继承)
- * [组合与继承的选择](docs/book/08-Reuse.md#组合与继承的选择)
- * [protected](docs/book/08-Reuse.md#protected)
- * [向上转型](docs/book/08-Reuse.md#向上转型)
- * [final关键字](docs/book/08-Reuse.md#final关键字)
- * [类初始化和加载](docs/book/08-Reuse.md#类初始化和加载)
- * [本章小结](docs/book/08-Reuse.md#本章小结)
-* [第九章 多态](docs/book/09-Polymorphism.md)
- * [向上转型回溯](docs/book/09-Polymorphism.md#向上转型回溯)
- * [深入理解](docs/book/09-Polymorphism.md#深入理解)
- * [构造器和多态](docs/book/09-Polymorphism.md#构造器和多态)
- * [返回类型协变](docs/book/09-Polymorphism.md#返回类型协变)
- * [使用继承设计](docs/book/09-Polymorphism.md#使用继承设计)
- * [本章小结](docs/book/09-Polymorphism.md#本章小结)
-* [第十章 接口](docs/book/10-Interfaces.md)
- * [抽象类和方法](docs/book/10-Interfaces.md#抽象类和方法)
- * [接口创建](docs/book/10-Interfaces.md#接口创建)
- * [抽象类和接口](docs/book/10-Interfaces.md#抽象类和接口)
- * [完全解耦](docs/book/10-Interfaces.md#完全解耦)
- * [多接口结合](docs/book/10-Interfaces.md#多接口结合)
- * [使用继承扩展接口](docs/book/10-Interfaces.md#使用继承扩展接口)
- * [接口适配](docs/book/10-Interfaces.md#接口适配)
- * [接口字段](docs/book/10-Interfaces.md#接口字段)
- * [接口嵌套](docs/book/10-Interfaces.md#接口嵌套)
- * [接口和工厂方法模式](docs/book/10-Interfaces.md#接口和工厂方法模式)
- * [本章小结](docs/book/10-Interfaces.md#本章小结)
-* [第十一章 内部类](docs/book/11-Inner-Classes.md)
- * [创建内部类](docs/book/11-Inner-Classes.md#创建内部类)
- * [链接外部类](docs/book/11-Inner-Classes.md#链接外部类)
- * [内部类this和new的使用](docs/book/11-Inner-Classes.md#内部类this和new的使用)
- * [内部类向上转型](docs/book/11-Inner-Classes.md#内部类向上转型)
- * [内部类方法和作用域](docs/book/11-Inner-Classes.md#内部类方法和作用域)
- * [匿名内部类](docs/book/11-Inner-Classes.md#匿名内部类)
- * [嵌套类](docs/book/11-Inner-Classes.md#嵌套类)
- * [为什么需要内部类](docs/book/11-Inner-Classes.md#为什么需要内部类)
- * [继承内部类](docs/book/11-Inner-Classes.md#继承内部类)
- * [重写内部类](docs/book/11-Inner-Classes.md#重写内部类)
- * [内部类局部变量](docs/book/11-Inner-Classes.md#内部类局部变量)
- * [内部类标识符](docs/book/11-Inner-Classes.md#内部类标识符)
- * [本章小结](docs/book/11-Inner-Classes.md#本章小结)
-* [第十二章 集合](docs/book/12-Collections.md)
- * [泛型和类型安全的集合](docs/book/12-Collections.md#泛型和类型安全的集合)
- * [基本概念](docs/book/12-Collections.md#基本概念)
- * [添加元素组](docs/book/12-Collections.md#添加元素组)
- * [集合的打印](docs/book/12-Collections.md#集合的打印)
- * [列表List](docs/book/12-Collections.md#列表List)
- * [迭代器Iterators](docs/book/12-Collections.md#迭代器Iterators)
- * [链表LinkedList](docs/book/12-Collections.md#链表LinkedList)
- * [堆栈Stack](docs/book/12-Collections.md#堆栈Stack)
- * [集合Set](docs/book/12-Collections.md#集合Set)
- * [映射Map](docs/book/12-Collections.md#映射Map)
- * [队列Queue](docs/book/12-Collections.md#队列Queue)
- * [集合与迭代器](docs/book/12-Collections.md#集合与迭代器)
- * [for-in和迭代器](docs/book/12-Collections.md#for-in和迭代器)
- * [本章小结](docs/book/12-Collections.md#本章小结)
-* [第十三章 函数式编程](docs/book/13-Functional-Programming.md)
- * [新旧对比](docs/book/13-Functional-Programming.md#新旧对比)
- * [Lambda表达式](docs/book/13-Functional-Programming.md#Lambda表达式)
- * [方法引用](docs/book/13-Functional-Programming.md#方法引用)
- * [函数式接口](docs/book/13-Functional-Programming.md#函数式接口)
- * [高阶函数](docs/book/13-Functional-Programming.md#高阶函数)
- * [闭包](docs/book/13-Functional-Programming.md#闭包)
- * [函数组合](docs/book/13-Functional-Programming.md#函数组合)
- * [柯里化和部分求值](docs/book/13-Functional-Programming.md#柯里化和部分求值)
- * [纯函数式编程](docs/book/13-Functional-Programming.md#纯函数式编程)
- * [本章小结](docs/book/13-Functional-Programming.md#本章小结)
-* [第十四章 流式编程](docs/book/14-Streams.md)
- * [流支持](docs/book/14-Streams.md#流支持)
- * [流创建](docs/book/14-Streams.md#流创建)
- * [中级流操作](docs/book/14-Streams.md#中级流操作)
- * [Optional类](docs/book/14-Streams.md#Optional类)
- * [终端操作](docs/book/14-Streams.md#终端操作)
- * [本章小结](docs/book/14-Streams.md#本章小结)
-* [第十五章 异常](docs/book/15-Exceptions.md)
- * [异常概念](docs/book/15-Exceptions.md#异常概念)
- * [基本异常](docs/book/15-Exceptions.md#基本异常)
- * [异常捕获](docs/book/15-Exceptions.md#异常捕获)
- * [自定义异常](docs/book/15-Exceptions.md#自定义异常)
- * [异常规范](docs/book/15-Exceptions.md#异常规范)
- * [任意异常捕获](docs/book/15-Exceptions.md#任意异常捕获)
- * [Java标准异常](docs/book/15-Exceptions.md#Java标准异常)
- * [finally关键字](docs/book/15-Exceptions.md#finally关键字)
- * [异常限制](docs/book/15-Exceptions.md#异常限制)
- * [异常构造](docs/book/15-Exceptions.md#异常构造)
- * [Try-With-Resources用法](docs/book/15-Exceptions.md#Try-With-Resources用法)
- * [异常匹配](docs/book/15-Exceptions.md#异常匹配)
- * [异常准则](docs/book/15-Exceptions.md#异常准则)
- * [异常指南](docs/book/15-Exceptions.md#异常指南)
- * [本章小结](docs/book/15-Exceptions.md#本章小结)
-* [第十六章 代码校验](docs/book/16-Validating-Your-Code.md)
- * [测试](docs/book/16-Validating-Your-Code.md#测试)
- * [前提条件](docs/book/16-Validating-Your-Code.md#前提条件)
- * [测试驱动开发](docs/book/16-Validating-Your-Code.md#测试驱动开发)
- * [日志](docs/book/16-Validating-Your-Code.md#日志)
- * [调试](docs/book/16-Validating-Your-Code.md#调试)
- * [基准测试](docs/book/16-Validating-Your-Code.md#基准测试)
- * [分析和优化](docs/book/16-Validating-Your-Code.md#分析和优化)
- * [风格检测](docs/book/16-Validating-Your-Code.md#风格检测)
- * [静态错误分析](docs/book/16-Validating-Your-Code.md#静态错误分析)
- * [代码重审](docs/book/16-Validating-Your-Code.md#代码重审)
- * [结对编程](docs/book/16-Validating-Your-Code.md#结对编程)
- * [重构](docs/book/16-Validating-Your-Code.md#重构)
- * [持续集成](docs/book/16-Validating-Your-Code.md#持续集成)
- * [本章小结](docs/book/16-Validating-Your-Code.md#本章小结)
-* [第十七章 文件](docs/book/17-Files.md)
- * [文件和目录路径](docs/book/17-Files.md#文件和目录路径)
- * [目录](docs/book/17-Files.md#目录)
- * [文件系统](docs/book/17-Files.md#文件系统)
- * [路径监听](docs/book/17-Files.md#路径监听)
- * [文件查找](docs/book/17-Files.md#文件查找)
- * [文件读写](docs/book/17-Files.md#文件读写)
- * [本章小结](docs/book/17-Files.md#本章小结)
-* [第十八章 字符串](docs/book/18-Strings.md)
- * [字符串的不可变](docs/book/18-Strings.md#字符串的不可变)
- * [重载和StringBuilder](docs/book/18-Strings.md#重载和StringBuilder)
- * [意外递归](docs/book/18-Strings.md#意外递归)
- * [字符串操作](docs/book/18-Strings.md#字符串操作)
- * [格式化输出](docs/book/18-Strings.md#格式化输出)
- * [常规表达式](docs/book/18-Strings.md#常规表达式)
- * [扫描输入](docs/book/18-Strings.md#扫描输入)
- * [StringTokenizer类](docs/book/18-Strings.md#StringTokenizer类)
- * [本章小结](docs/book/18-Strings.md#本章小结)
-* [第十九章 类型信息](docs/book/19-Type-Information.md)
- * [运行时类型信息](docs/book/19-Type-Information.md#运行时类型信息)
- * [类的对象](docs/book/19-Type-Information.md#类的对象)
- * [类型转换检测](docs/book/19-Type-Information.md#类型转换检测)
- * [注册工厂](docs/book/19-Type-Information.md#注册工厂)
- * [类的等价比较](docs/book/19-Type-Information.md#类的等价比较)
- * [反射运行时类信息](docs/book/19-Type-Information.md#反射运行时类信息)
- * [动态代理](docs/book/19-Type-Information.md#动态代理)
- * [Optional类](docs/book/19-Type-Information.md#Optional类)
- * [接口和类型](docs/book/19-Type-Information.md#接口和类型)
- * [本章小结](docs/book/19-Type-Information.md#本章小结)
-* [第二十章 泛型](docs/book/20-Generics.md)
- * [简单泛型](docs/book/20-Generics.md#简单泛型)
- * [泛型接口](docs/book/20-Generics.md#泛型接口)
- * [泛型方法](docs/book/20-Generics.md#泛型方法)
- * [复杂模型构建](docs/book/20-Generics.md#复杂模型构建)
- * [泛型擦除](docs/book/20-Generics.md#泛型擦除)
- * [补偿擦除](docs/book/20-Generics.md#补偿擦除)
- * [边界](docs/book/20-Generics.md#边界)
- * [通配符](docs/book/20-Generics.md#通配符)
- * [问题](docs/book/20-Generics.md#问题)
- * [自我约束类型](docs/book/20-Generics.md#自我约束类型)
- * [动态类型安全](docs/book/20-Generics.md#动态类型安全)
- * [泛型异常](docs/book/20-Generics.md#泛型异常)
- * [混入](docs/book/20-Generics.md#混入)
- * [潜在类型](docs/book/20-Generics.md#潜在类型)
- * [补偿不足](docs/book/20-Generics.md#补偿不足)
- * [辅助潜在类型](docs/book/20-Generics.md#辅助潜在类型)
- * [泛型的优劣](docs/book/20-Generics.md#泛型的优劣)
-* [第二十一章 数组](docs/book/21-Arrays.md)
- * [数组特性](docs/book/21-Arrays.md#数组特性)
- * [一等对象](docs/book/21-Arrays.md#一等对象)
- * [返回数组](docs/book/21-Arrays.md#返回数组)
- * [多维数组](docs/book/21-Arrays.md#多维数组)
- * [泛型数组](docs/book/21-Arrays.md#泛型数组)
- * [Arrays的fill方法](docs/book/21-Arrays.md#Arrays的fill方法)
- * [Arrays的setAll方法](docs/book/21-Arrays.md#Arrays的setAll方法)
- * [增量生成](docs/book/21-Arrays.md#增量生成)
- * [随机生成](docs/book/21-Arrays.md#随机生成)
- * [泛型和基本数组](docs/book/21-Arrays.md#泛型和基本数组)
- * [数组元素修改](docs/book/21-Arrays.md#数组元素修改)
- * [数组并行](docs/book/21-Arrays.md#数组并行)
- * [Arrays工具类](docs/book/21-Arrays.md#Arrays工具类)
- * [数组拷贝](docs/book/21-Arrays.md#数组拷贝)
- * [数组比较](docs/book/21-Arrays.md#数组比较)
- * [流和数组](docs/book/21-Arrays.md#流和数组)
- * [数组排序](docs/book/21-Arrays.md#数组排序)
- * [binarySearch二分查找](docs/book/21-Arrays.md#binarySearch二分查找)
- * [parallelPrefix并行前缀](docs/book/21-Arrays.md#parallelPrefix并行前缀)
- * [本章小结](docs/book/21-Arrays.md#本章小结)
-* [第二十二章 枚举](docs/book/22-Enumerations.md)
- * [基本功能](docs/book/22-Enumerations.md#基本功能)
- * [方法添加](docs/book/22-Enumerations.md#方法添加)
- * [switch语句](docs/book/22-Enumerations.md#switch语句)
- * [values方法](docs/book/22-Enumerations.md#values方法)
- * [实现而非继承](docs/book/22-Enumerations.md#实现而非继承)
- * [随机选择](docs/book/22-Enumerations.md#随机选择)
- * [使用接口组织](docs/book/22-Enumerations.md#使用接口组织)
- * [使用EnumSet替代Flags](docs/book/22-Enumerations.md#使用EnumSet替代Flags)
- * [使用EnumMap](docs/book/22-Enumerations.md#使用EnumMap)
- * [常量特定方法](docs/book/22-Enumerations.md#常量特定方法)
- * [多次调度](docs/book/22-Enumerations.md#多次调度)
- * [本章小结](docs/book/22-Enumerations.md#本章小结)
-* [第二十三章 注解](docs/book/23-Annotations.md)
- * [基本语法](docs/book/23-Annotations.md#基本语法)
- * [编写注解处理器](docs/book/23-Annotations.md#编写注解处理器)
- * [使用javac处理注解](docs/book/23-Annotations.md#使用javac处理注解)
- * [基于注解的单元测试](docs/book/23-Annotations.md#基于注解的单元测试)
- * [本章小结](docs/book/23-Annotations.md#本章小结)
-* [第二十四章 并发编程](docs/book/24-Concurrent-Programming.md)
- * [术语问题](docs/book/24-Concurrent-Programming.md#术语问题)
- * [并发的超能力](docs/book/24-Concurrent-Programming.md#并发的超能力)
- * [针对速度](docs/book/24-Concurrent-Programming.md#针对速度)
- * [四句格言](docs/book/24-Concurrent-Programming.md#四句格言)
- * [残酷的真相](docs/book/24-Concurrent-Programming.md#残酷的真相)
- * [本章其余部分](docs/book/24-Concurrent-Programming.md#本章其余部分)
- * [并行流](docs/book/24-Concurrent-Programming.md#并行流)
- * [创建和运行任务](docs/book/24-Concurrent-Programming.md#创建和运行任务)
- * [终止耗时任务](docs/book/24-Concurrent-Programming.md#终止耗时任务)
- * [CompletableFuture类](docs/book/24-Concurrent-Programming.md#CompletableFuture类)
- * [死锁](docs/book/24-Concurrent-Programming.md#死锁)
- * [构造函数非线程安全](docs/book/24-Concurrent-Programming.md#构造函数非线程安全)
- * [复杂性和代价](docs/book/24-Concurrent-Programming.md#复杂性和代价)
- * [本章小结](docs/book/24-Concurrent-Programming.md#本章小结)
-* [第二十五章 设计模式](docs/book/25-Patterns.md)
- * [概念](docs/book/25-Patterns.md#概念)
- * [构建型](docs/book/25-Patterns.md#构建型)
- * [面向实施](docs/book/25-Patterns.md#面向实施)
- * [工厂模式](docs/book/25-Patterns.md#工厂模式)
- * [函数对象](docs/book/25-Patterns.md#函数对象)
- * [接口改变](docs/book/25-Patterns.md#接口改变)
- * [解释器](docs/book/25-Patterns.md#解释器)
- * [回调](docs/book/25-Patterns.md#回调)
- * [多次调度](docs/book/25-Patterns.md#多次调度)
- * [模式重构](docs/book/25-Patterns.md#模式重构)
- * [抽象用法](docs/book/25-Patterns.md#抽象用法)
- * [多次派遣](docs/book/25-Patterns.md#多次派遣)
- * [访问者模式](docs/book/25-Patterns.md#访问者模式)
- * [RTTI的优劣](docs/book/25-Patterns.md#RTTI的优劣)
- * [本章小结](docs/book/25-Patterns.md#本章小结)
-
-* [附录:补充](docs/book/Appendix-Supplements.md)
- * [可下载的补充](docs/book/Appendix-Supplements.md#可下载的补充)
- * [通过Thinking-in-C来巩固Java基础](docs/book/Appendix-Supplements.md#通过Thinking-in-C来巩固Java基础)
- * [动手实践](docs/book/Appendix-Supplements.md#动手实践)
-* [附录:编程指南](docs/book/Appendix-Programming-Guidelines.md)
- * [设计](docs/book/Appendix-Programming-Guidelines.md#设计)
- * [实现](docs/book/Appendix-Programming-Guidelines.md#实现)
-* [附录:文档注释](docs/book/Appendix-Javadoc.md)
-* [附录:对象传递和返回](docs/book/Appendix-Passing-and-Returning-Objects.md)
- * [传递引用](docs/book/Appendix-Passing-and-Returning-Objects.md#传递引用)
- * [本地拷贝](docs/book/Appendix-Passing-and-Returning-Objects.md#本地拷贝)
- * [控制克隆](docs/book/Appendix-Passing-and-Returning-Objects.md#控制克隆)
- * [不可变类](docs/book/Appendix-Passing-and-Returning-Objects.md#不可变类)
- * [本章小结](docs/book/Appendix-Passing-and-Returning-Objects.md#本章小结)
-* [附录:流式IO](docs/book/Appendix-IO-Streams.md)
- * [输入流类型](docs/book/Appendix-IO-Streams.md#输入流类型)
- * [输出流类型](docs/book/Appendix-IO-Streams.md#输出流类型)
- * [添加属性和有用的接口](docs/book/Appendix-IO-Streams.md#添加属性和有用的接口)
- * [Reader和Writer](docs/book/Appendix-IO-Streams.md#Reader和Writer)
- * [RandomAccessFile类](docs/book/Appendix-IO-Streams.md#RandomAccessFile类)
- * [IO流典型用途](docs/book/Appendix-IO-Streams.md#IO流典型用途)
- * [本章小结](docs/book/Appendix-IO-Streams.md#本章小结)
-* [附录:标准IO](docs/book/Appendix-Standard-IO.md)
- * [执行控制](docs/book/Appendix-Standard-IO.md#执行控制)
-* [附录:新IO](docs/book/Appendix-New-IO.md)
- * [ByteBuffer](docs/book/Appendix-New-IO.md#ByteBuffer)
- * [转换数据](docs/book/Appendix-New-IO.md#数据转换)
- * [获取原始类型](docs/book/Appendix-New-IO.md#基本类型获取)
- * [视图缓冲区](docs/book/Appendix-New-IO.md#视图缓冲区)
- * [使用缓冲区进行数据操作](docs/book/Appendix-New-IO.md#缓冲区数据操作)
- * [内存映射文件](docs/book/Appendix-New-IO.md#内存映射文件)
- * [文件锁定](docs/book/Appendix-New-IO.md#文件锁定)
-* [附录:理解equals和hashCode方法](docs/book/Appendix-Understanding-equals-and-hashCode.md)
- * [equals典范](docs/book/Appendix-Understanding-equals-and-hashCode.md#equals典范)
- * [哈希和哈希码](docs/book/Appendix-Understanding-equals-and-hashCode.md#哈希和哈希码)
- * [调整HashMap](docs/book/Appendix-Understanding-equals-and-hashCode.md#调整HashMap)
-* [附录:集合主题](docs/book/Appendix-Collection-Topics.md)
- * [示例数据](docs/book/Appendix-Collection-Topics.md#示例数据)
- * [List行为](docs/book/Appendix-Collection-Topics.md#List行为)
- * [Set行为](docs/book/Appendix-Collection-Topics.md#Set行为)
- * [在Map中使用函数式操作](docs/book/Appendix-Collection-Topics.md#在Map中使用函数式操作)
- * [选择Map片段](docs/book/Appendix-Collection-Topics.md#选择Map片段)
- * [填充集合](docs/book/Appendix-Collection-Topics.md#填充集合)
- * [使用享元(Flyweight)自定义Collection和Map](docs/book/Appendix-Collection-Topics.md#使用享元(Flyweight)自定义Collection和Map)
- * [集合功能](docs/book/Appendix-Collection-Topics.md#集合功能)
- * [可选操作](docs/book/Appendix-Collection-Topics.md#可选操作)
- * [Set和存储顺序](docs/book/Appendix-Collection-Topics.md#Set和存储顺序)
- * [队列](docs/book/Appendix-Collection-Topics.md#队列)
- * [理解Map](docs/book/Appendix-Collection-Topics.md#理解Map)
- * [集合工具类](docs/book/Appendix-Collection-Topics.md#集合工具类)
- * [持有引用](docs/book/Appendix-Collection-Topics.md#持有引用)
- * [Java 1.0 / 1.1 的集合类](docs/book/Appendix-Collection-Topics.md#避免旧式类库)
- * [本章小结](docs/book/Appendix-Collection-Topics.md#本章小结)
-* [附录:并发底层原理](docs/book/Appendix-Low-Level-Concurrency.md)
- * [线程](docs/book/Appendix-Low-Level-Concurrency.md#线程)
- * [异常捕获](docs/book/Appendix-Low-Level-Concurrency.md#异常捕获)
- * [资源共享](docs/book/Appendix-Low-Level-Concurrency.md#资源共享)
- * [volatile关键字](docs/book/Appendix-Low-Level-Concurrency.md#volatile关键字)
- * [原子性](docs/book/Appendix-Low-Level-Concurrency.md#原子性)
- * [临界区](docs/book/Appendix-Low-Level-Concurrency.md#临界区)
- * [库组件](docs/book/Appendix-Low-Level-Concurrency.md#库组件)
- * [本章小结](docs/book/Appendix-Low-Level-Concurrency.md#本章小结)
-* [附录:数据压缩](docs/book/Appendix-Data-Compression.md)
- * [使用Gzip简单压缩](docs/book/Appendix-Data-Compression.md#使用Gzip简单压缩)
- * [使用zip多文件存储](docs/book/Appendix-Data-Compression.md#使用zip多文件存储)
- * [Java的jar](docs/book/Appendix-Data-Compression.md#Java的jar)
-* [附录:对象序列化](docs/book/Appendix-Object-Serialization.md)
- * [查找类](docs/book/Appendix-Object-Serialization.md#查找类)
- * [控制序列化](docs/book/Appendix-Object-Serialization.md#控制序列化)
- * [使用持久化](docs/book/Appendix-Object-Serialization.md#使用持久化)
-* [附录:静态语言类型检查](docs/book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md)
- * [前言](docs/book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md#前言)
- * [静态类型检查和测试](docs/book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md#静态类型检查和测试)
- * [如何提升打字](docs/book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md#如何提升打字)
- * [生产力的成本](docs/book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md#生产力的成本)
- * [静态和动态](docs/book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md#静态和动态)
-* [附录:C++和Java的优良传统](docs/book/Appendix-The-Positive-Legacy-of-C-plus-plus-and-Java.md)
-* [附录:成为一名程序员](docs/book/Appendix-Becoming-a-Programmer.md)
- * [如何开始](docs/book/Appendix-Becoming-a-Programmer.md#如何开始)
- * [码农生涯](docs/book/Appendix-Becoming-a-Programmer.md#码农生涯)
- * [百分之五的神话](docs/book/Appendix-Becoming-a-Programmer.md#百分之五的神话)
- * [重在动手](docs/book/Appendix-Becoming-a-Programmer.md#重在动手)
- * [像打字般编程](docs/book/Appendix-Becoming-a-Programmer.md#像打字般编程)
- * [做你喜欢的事](docs/book/Appendix-Becoming-a-Programmer.md#做你喜欢的事)
-* [词汇表](docs/book/GLOSSARY.md)
+
+### [译者的话](README.md)
+
+### [封面](book/00-On-Java-8.md)
+
+### [前言](book/00-Preface.md)
+
+### [简介](book/00-Introduction.md)
+
+### [第一章 对象的概念](book/01-What-is-an-Object.md)
+ * [抽象](book/01-What-is-an-Object.md#抽象)
+ * [接口](book/01-What-is-an-Object.md#接口)
+ * [服务提供](book/01-What-is-an-Object.md#服务提供)
+ * [封装](book/01-What-is-an-Object.md#封装)
+ * [复用](book/01-What-is-an-Object.md#复用)
+ * [继承](book/01-What-is-an-Object.md#继承)
+ * [多态](book/01-What-is-an-Object.md#多态)
+ * [单继承结构](book/01-What-is-an-Object.md#单继承结构)
+ * [集合](book/01-What-is-an-Object.md#集合)
+ * [对象创建与生命周期](book/01-What-is-an-Object.md#对象创建与生命周期)
+ * [异常处理](book/01-What-is-an-Object.md#异常处理)
+ * [本章小结](book/01-What-is-an-Object.md#本章小结)
+
+### [第二章 安装Java和本书用例](book/02-Installing-Java-and-the-Book-Examples.md)
+ * [编辑器](book/02-Installing-Java-and-the-Book-Examples.md#编辑器)
+ * [Shell](book/02-Installing-Java-and-the-Book-Examples.md#Shell)
+ * [Java安装](book/02-Installing-Java-and-the-Book-Examples.md#Java安装)
+ * [校验安装](book/02-Installing-Java-and-the-Book-Examples.md#校验安装)
+ * [安装和运行代码示例](book/02-Installing-Java-and-the-Book-Examples.md#安装和运行代码示例)
+
+### [第三章 万物皆对象](book/03-Objects-Everywhere.md)
+ * [对象操纵](book/03-Objects-Everywhere.md#对象操纵)
+ * [对象创建](book/03-Objects-Everywhere.md#对象创建)
+ * [代码注释](book/03-Objects-Everywhere.md#代码注释)
+ * [对象清理](book/03-Objects-Everywhere.md#对象清理)
+ * [类的创建](book/03-Objects-Everywhere.md#类的创建)
+ * [程序编写](book/03-Objects-Everywhere.md#程序编写)
+ * [小试牛刀](book/03-Objects-Everywhere.md#小试牛刀)
+ * [编码风格](book/03-Objects-Everywhere.md#编码风格)
+ * [本章小结](book/03-Objects-Everywhere.md#本章小结)
+
+### [第四章 运算符](book/04-Operators.md)
+ * [开始使用](book/04-Operators.md#开始使用)
+ * [优先级](book/04-Operators.md#优先级)
+ * [赋值](book/04-Operators.md#赋值)
+ * [算术运算符](book/04-Operators.md#算术运算符)
+ * [递增和递减](book/04-Operators.md#递增和递减)
+ * [关系运算符](book/04-Operators.md#关系运算符)
+ * [逻辑运算符](book/04-Operators.md#逻辑运算符)
+ * [字面值常量](book/04-Operators.md#字面值常量)
+ * [位运算符](book/04-Operators.md#位运算符)
+ * [移位运算符](book/04-Operators.md#移位运算符)
+ * [三元运算符](book/04-Operators.md#三元运算符)
+ * [字符串运算符](book/04-Operators.md#字符串运算符)
+ * [常见陷阱](book/04-Operators.md#常见陷阱)
+ * [类型转换](book/04-Operators.md#类型转换)
+ * [Java没有sizeof](book/04-Operators.md#Java没有sizeof)
+ * [运算符总结](book/04-Operators.md#运算符总结)
+ * [本章小结](book/04-Operators.md#本章小结)
+
+### [第五章 控制流](book/05-Control-Flow.md)
+ * [true和false](book/05-Control-Flow.md#true和false)
+ * [if-else](book/05-Control-Flow.md#if-else)
+ * [迭代语句](book/05-Control-Flow.md#迭代语句)
+ * [for-in 语法](book/05-Control-Flow.md#for-in-语法)
+ * [return](book/05-Control-Flow.md#return)
+ * [break 和 continue](book/05-Control-Flow.md#break-和-continue)
+ * [臭名昭著的 goto](book/05-Control-Flow.md#臭名昭著的-goto)
+ * [switch](book/05-Control-Flow.md#switch)
+ * [switch 字符串](book/05-Control-Flow.md#switch-字符串)
+ * [本章小结](book/05-Control-Flow.md#本章小结)
+
+### [第六章 初始化和清理](book/06-Housekeeping.md)
+ * [利用构造器保证初始化](book/06-Housekeeping.md#利用构造器保证初始化)
+ * [方法重载](book/06-Housekeeping.md#方法重载)
+ * [无参构造器](book/06-Housekeeping.md#无参构造器)
+ * [this关键字](book/06-Housekeeping.md#this关键字)
+ * [垃圾回收器](book/06-Housekeeping.md#垃圾回收器)
+ * [成员初始化](book/06-Housekeeping.md#成员初始化)
+ * [构造器初始化](book/06-Housekeeping.md#构造器初始化)
+ * [数组初始化](book/06-Housekeeping.md#数组初始化)
+ * [枚举类型](book/06-Housekeeping.md#枚举类型)
+ * [本章小结](book/06-Housekeeping.md#本章小结)
+
+### [第七章 封装](book/07-Implementation-Hiding.md)
+ * [包的概念](book/07-Implementation-Hiding.md#包的概念)
+ * [访问权限修饰符](book/07-Implementation-Hiding.md#访问权限修饰符)
+ * [接口和实现](book/07-Implementation-Hiding.md#接口和实现)
+ * [类访问权限](book/07-Implementation-Hiding.md#类访问权限)
+ * [本章小结](book/07-Implementation-Hiding.md#本章小结)
+
+### [第八章 复用](book/08-Reuse.md)
+ * [组合语法](book/08-Reuse.md#组合语法)
+ * [继承语法](book/08-Reuse.md#继承语法)
+ * [委托](book/08-Reuse.md#委托)
+ * [结合组合与继承](book/08-Reuse.md#结合组合与继承)
+ * [组合与继承的选择](book/08-Reuse.md#组合与继承的选择)
+ * [protected](book/08-Reuse.md#protected)
+ * [向上转型](book/08-Reuse.md#向上转型)
+ * [final关键字](book/08-Reuse.md#final关键字)
+ * [类初始化和加载](book/08-Reuse.md#类初始化和加载)
+ * [本章小结](book/08-Reuse.md#本章小结)
+
+### [第九章 多态](book/09-Polymorphism.md)
+ * [向上转型回顾](book/09-Polymorphism.md#向上转型回顾)
+ * [转机](book/09-Polymorphism.md#转机)
+ * [构造器和多态](book/09-Polymorphism.md#构造器和多态)
+ * [协变返回类型](book/09-Polymorphism.md#协变返回类型)
+ * [使用继承设计](book/09-Polymorphism.md#使用继承设计)
+ * [本章小结](book/09-Polymorphism.md#本章小结)
+
+### [第十章 接口](book/10-Interfaces.md)
+ * [抽象类和方法](book/10-Interfaces.md#抽象类和方法)
+ * [接口创建](book/10-Interfaces.md#接口创建)
+ * [抽象类和接口](book/10-Interfaces.md#抽象类和接口)
+ * [完全解耦](book/10-Interfaces.md#完全解耦)
+ * [多接口结合](book/10-Interfaces.md#多接口结合)
+ * [使用继承扩展接口](book/10-Interfaces.md#使用继承扩展接口)
+ * [接口适配](book/10-Interfaces.md#接口适配)
+ * [接口字段](book/10-Interfaces.md#接口字段)
+ * [接口嵌套](book/10-Interfaces.md#接口嵌套)
+ * [接口和工厂方法模式](book/10-Interfaces.md#接口和工厂方法模式)
+ * [本章小结](book/10-Interfaces.md#本章小结)
+
+### [第十一章 内部类](book/11-Inner-Classes.md)
+ * [创建内部类](book/11-Inner-Classes.md#创建内部类)
+ * [链接外部类](book/11-Inner-Classes.md#链接外部类)
+ * [使用 .this 和 .new](book/11-Inner-Classes.md#使用-this-和-new)
+ * [内部类与向上转型](book/11-Inner-Classes.md#内部类与向上转型)
+ * [内部类方法和作用域](book/11-Inner-Classes.md#内部类方法和作用域)
+ * [匿名内部类](book/11-Inner-Classes.md#匿名内部类)
+ * [嵌套类](book/11-Inner-Classes.md#嵌套类)
+ * [为什么需要内部类](book/11-Inner-Classes.md#为什么需要内部类)
+ * [继承内部类](book/11-Inner-Classes.md#继承内部类)
+ * [内部类可以被覆盖么?](book/11-Inner-Classes.md#内部类可以被覆盖么?)
+ * [局部内部类](book/11-Inner-Classes.md#局部内部类)
+ * [内部类标识符](book/11-Inner-Classes.md#内部类标识符)
+ * [本章小结](book/11-Inner-Classes.md#本章小结)
+
+### [第十二章 集合](book/12-Collections.md)
+ * [泛型和类型安全的集合](book/12-Collections.md#泛型和类型安全的集合)
+ * [基本概念](book/12-Collections.md#基本概念)
+ * [添加元素组](book/12-Collections.md#添加元素组)
+ * [集合的打印](book/12-Collections.md#集合的打印)
+ * [列表List](book/12-Collections.md#列表List)
+ * [迭代器Iterators](book/12-Collections.md#迭代器Iterators)
+ * [链表LinkedList](book/12-Collections.md#链表LinkedList)
+ * [堆栈Stack](book/12-Collections.md#堆栈Stack)
+ * [集合Set](book/12-Collections.md#集合Set)
+ * [映射Map](book/12-Collections.md#映射Map)
+ * [队列Queue](book/12-Collections.md#队列Queue)
+ * [集合与迭代器](book/12-Collections.md#集合与迭代器)
+ * [for-in和迭代器](book/12-Collections.md#for-in和迭代器)
+ * [本章小结](book/12-Collections.md#本章小结)
+
+### [第十三章 函数式编程](book/13-Functional-Programming.md)
+ * [新旧对比](book/13-Functional-Programming.md#新旧对比)
+ * [Lambda表达式](book/13-Functional-Programming.md#Lambda表达式)
+ * [方法引用](book/13-Functional-Programming.md#方法引用)
+ * [函数式接口](book/13-Functional-Programming.md#函数式接口)
+ * [高阶函数](book/13-Functional-Programming.md#高阶函数)
+ * [闭包](book/13-Functional-Programming.md#闭包)
+ * [函数组合](book/13-Functional-Programming.md#函数组合)
+ * [柯里化和部分求值](book/13-Functional-Programming.md#柯里化和部分求值)
+ * [纯函数式编程](book/13-Functional-Programming.md#纯函数式编程)
+ * [本章小结](book/13-Functional-Programming.md#本章小结)
+
+### [第十四章 流式编程](book/14-Streams.md)
+ * [流支持](book/14-Streams.md#流支持)
+ * [流创建](book/14-Streams.md#流创建)
+ * [中间操作](book/14-Streams.md#中间操作)
+ * [Optional类](book/14-Streams.md#Optional类)
+ * [终端操作](book/14-Streams.md#终端操作)
+ * [本章小结](book/14-Streams.md#本章小结)
+
+### [第十五章 异常](book/15-Exceptions.md)
+ * [异常概念](book/15-Exceptions.md#异常概念)
+ * [基本异常](book/15-Exceptions.md#基本异常)
+ * [异常捕获](book/15-Exceptions.md#异常捕获)
+ * [自定义异常](book/15-Exceptions.md#自定义异常)
+ * [异常声明](book/15-Exceptions.md#异常声明)
+ * [捕获所有异常](book/15-Exceptions.md#捕获所有异常)
+ * [Java 标准异常](book/15-Exceptions.md#Java-标准异常)
+ * [使用 finally 进行清理](book/15-Exceptions.md#使用-finally-进行清理)
+ * [异常限制](book/15-Exceptions.md#异常限制)
+ * [构造器](book/15-Exceptions.md#构造器)
+ * [Try-With-Resources 用法](book/15-Exceptions.md#Try-With-Resources-用法)
+ * [异常匹配](book/15-Exceptions.md#异常匹配)
+ * [其他可选方式](book/15-Exceptions.md#其他可选方式)
+ * [异常指南](book/15-Exceptions.md#异常指南)
+ * [本章小结](book/15-Exceptions.md#本章小结)
+ * [后记:Exception Bizarro World](book/15-Exceptions.md#后记:Exception-Bizarro-World)
+
+### [第十六章 代码校验](book/16-Validating-Your-Code.md)
+ * [测试](book/16-Validating-Your-Code.md#测试)
+ * [前置条件](book/16-Validating-Your-Code.md#前置条件)
+ * [测试驱动开发](book/16-Validating-Your-Code.md#测试驱动开发)
+ * [日志](book/16-Validating-Your-Code.md#日志)
+ * [调试](book/16-Validating-Your-Code.md#调试)
+ * [基准测试](book/16-Validating-Your-Code.md#基准测试)
+ * [剖析和优化](book/16-Validating-Your-Code.md#剖析和优化)
+ * [风格检测](book/16-Validating-Your-Code.md#风格检测)
+ * [静态错误分析](book/16-Validating-Your-Code.md#静态错误分析)
+ * [代码重审](book/16-Validating-Your-Code.md#代码重审)
+ * [结对编程](book/16-Validating-Your-Code.md#结对编程)
+ * [重构](book/16-Validating-Your-Code.md#重构)
+ * [持续集成](book/16-Validating-Your-Code.md#持续集成)
+ * [本章小结](book/16-Validating-Your-Code.md#本章小结)
+
+### [第十七章 文件](book/17-Files.md)
+ * [文件和目录路径](book/17-Files.md#文件和目录路径)
+ * [目录](book/17-Files.md#目录)
+ * [文件系统](book/17-Files.md#文件系统)
+ * [路径监听](book/17-Files.md#路径监听)
+ * [文件查找](book/17-Files.md#文件查找)
+ * [文件读写](book/17-Files.md#文件读写)
+ * [本章小结](book/17-Files.md#本章小结)
+
+### [第十八章 字符串](book/18-Strings.md)
+ * [字符串的不可变](book/18-Strings.md#字符串的不可变)
+ * [+ 的重载与 StringBuilder](book/18-Strings.md#+-的重载与-StringBuilder)
+ * [意外递归](book/18-Strings.md#意外递归)
+ * [字符串操作](book/18-Strings.md#字符串操作)
+ * [格式化输出](book/18-Strings.md#格式化输出)
+ * [正则表达式](book/18-Strings.md#正则表达式)
+ * [扫描输入](book/18-Strings.md#扫描输入)
+ * [StringTokenizer类](book/18-Strings.md#StringTokenizer类)
+ * [本章小结](book/18-Strings.md#本章小结)
+
+### [第十九章 类型信息](book/19-Type-Information.md)
+ * [为什么需要 RTTI](book/19-Type-Information.md#为什么需要-RTTI)
+ * [Class 对象](book/19-Type-Information.md#Class-对象)
+ * [类型转换检测](book/19-Type-Information.md#类型转换检测)
+ * [注册工厂](book/19-Type-Information.md#注册工厂)
+ * [类的等价比较](book/19-Type-Information.md#类的等价比较)
+ * [反射:运行时类信息](book/19-Type-Information.md#反射:运行时类信息)
+ * [动态代理](book/19-Type-Information.md#动态代理)
+ * [Optional类](book/19-Type-Information.md#Optional类)
+ * [接口和类型](book/19-Type-Information.md#接口和类型)
+ * [本章小结](book/19-Type-Information.md#本章小结)
+
+### [第二十章 泛型](book/20-Generics.md)
+ * [简单泛型](book/20-Generics.md#简单泛型)
+ * [泛型接口](book/20-Generics.md#泛型接口)
+ * [泛型方法](book/20-Generics.md#泛型方法)
+ * [构建复杂模型](book/20-Generics.md#构建复杂模型)
+ * [泛型擦除](book/20-Generics.md#泛型擦除)
+ * [补偿擦除](book/20-Generics.md#补偿擦除)
+ * [边界](book/20-Generics.md#边界)
+ * [通配符](book/20-Generics.md#通配符)
+ * [问题](book/20-Generics.md#问题)
+ * [自限定的类型](book/20-Generics.md#自限定的类型)
+ * [动态类型安全](book/20-Generics.md#动态类型安全)
+ * [泛型异常](book/20-Generics.md#泛型异常)
+ * [混型](book/20-Generics.md#混型)
+ * [潜在类型机制](book/20-Generics.md#潜在类型机制)
+ * [对缺乏潜在类型机制的补偿](book/20-Generics.md#对缺乏潜在类型机制的补偿)
+ * [Java8 中的辅助潜在类型](book/20-Generics.md#Java8-中的辅助潜在类型)
+ * [总结:类型转换真的如此之糟吗?](book/20-Generics.md#总结:类型转换真的如此之糟吗?)
+ * [进阶阅读](book/20-Generics.md#进阶阅读)
+
+### [第二十一章 数组](book/21-Arrays.md)
+ * [数组特性](book/21-Arrays.md#数组特性)
+ * [一等对象](book/21-Arrays.md#一等对象)
+ * [返回数组](book/21-Arrays.md#返回数组)
+ * [多维数组](book/21-Arrays.md#多维数组)
+ * [泛型数组](book/21-Arrays.md#泛型数组)
+ * [Arrays的fill方法](book/21-Arrays.md#Arrays的fill方法)
+ * [Arrays的setAll方法](book/21-Arrays.md#Arrays的setAll方法)
+ * [增量生成](book/21-Arrays.md#增量生成)
+ * [随机生成](book/21-Arrays.md#随机生成)
+ * [泛型和基本数组](book/21-Arrays.md#泛型和基本数组)
+ * [数组元素修改](book/21-Arrays.md#数组元素修改)
+ * [数组并行](book/21-Arrays.md#数组并行)
+ * [Arrays工具类](book/21-Arrays.md#Arrays工具类)
+ * [数组拷贝](book/21-Arrays.md#数组拷贝)
+ * [数组比较](book/21-Arrays.md#数组比较)
+ * [流和数组](book/21-Arrays.md#流和数组)
+ * [数组排序](book/21-Arrays.md#数组排序)
+ * [Arrays.sort 的使用](book/21-Arrays.md#Arrayssort-的使用)
+ * [并行排序](book/21-Arrays.md#并行排序)
+ * [binarySearch二分查找](book/21-Arrays.md#binarySearch二分查找)
+ * [parallelPrefix并行前缀](book/21-Arrays.md#parallelPrefix并行前缀)
+ * [本章小结](book/21-Arrays.md#本章小结)
+
+### [第二十二章 枚举](book/22-Enumerations.md)
+ * [基本 enum 特性](book/22-Enumerations.md#基本-enum-特性)
+ * [方法添加](book/22-Enumerations.md#方法添加)
+ * [switch 语句中的 enum](book/22-Enumerations.md#switch-语句中的-enum)
+ * [values 方法的神秘之处](book/22-Enumerations.md#values-方法的神秘之处)
+ * [实现而非继承](book/22-Enumerations.md#实现而非继承)
+ * [随机选择](book/22-Enumerations.md#随机选择)
+ * [使用接口组织枚举](book/22-Enumerations.md#使用接口组织枚举)
+ * [使用 EnumSet 替代 Flags](book/22-Enumerations.md#使用-EnumSet-替代-Flags)
+ * [使用 EnumMap](book/22-Enumerations.md#使用-EnumMap)
+ * [常量特定方法](book/22-Enumerations.md#常量特定方法)
+ * [多路分发](book/22-Enumerations.md#多路分发)
+ * [本章小结](book/22-Enumerations.md#本章小结)
+
+### [第二十三章 注解](book/23-Annotations.md)
+ * [基本语法](book/23-Annotations.md#基本语法)
+ * [编写注解处理器](book/23-Annotations.md#编写注解处理器)
+ * [使用javac处理注解](book/23-Annotations.md#使用javac处理注解)
+ * [基于注解的单元测试](book/23-Annotations.md#基于注解的单元测试)
+ * [本章小结](book/23-Annotations.md#本章小结)
+
+### [第二十四章 并发编程](book/24-Concurrent-Programming.md)
+ * [术语问题](book/24-Concurrent-Programming.md#术语问题)
+ * [并发的超能力](book/24-Concurrent-Programming.md#并发的超能力)
+ * [并发为速度而生](book/24-Concurrent-Programming.md#并发为速度而生)
+ * [四句格言](book/24-Concurrent-Programming.md#四句格言)
+ * [残酷的真相](book/24-Concurrent-Programming.md#残酷的真相)
+ * [本章其余部分](book/24-Concurrent-Programming.md#本章其余部分)
+ * [并行流](book/24-Concurrent-Programming.md#并行流)
+ * [创建和运行任务](book/24-Concurrent-Programming.md#创建和运行任务)
+ * [终止耗时任务](book/24-Concurrent-Programming.md#终止耗时任务)
+ * [CompletableFuture类](book/24-Concurrent-Programming.md#CompletableFuture类)
+ * [死锁](book/24-Concurrent-Programming.md#死锁)
+ * [构造方法非线程安全](book/24-Concurrent-Programming.md#构造方法非线程安全)
+ * [复杂性和代价](book/24-Concurrent-Programming.md#复杂性和代价)
+ * [本章小结](book/24-Concurrent-Programming.md#本章小结)
+
+### [第二十五章 设计模式](book/25-Patterns.md)
+ * [概念](book/25-Patterns.md#概念)
+ * [构建应用程序框架](book/25-Patterns.md#构建应用程序框架)
+ * [面向实现](book/25-Patterns.md#面向实现)
+ * [工厂模式](book/25-Patterns.md#工厂模式)
+ * [函数对象](book/25-Patterns.md#函数对象)
+ * [改变接口](book/25-Patterns.md#改变接口)
+ * [解释器:运行时的弹性](book/25-Patterns.md#解释器:运行时的弹性)
+ * [回调](book/25-Patterns.md#回调)
+ * [多次调度](book/25-Patterns.md#多次调度)
+ * [模式重构](book/25-Patterns.md#模式重构)
+ * [抽象用法](book/25-Patterns.md#抽象用法)
+ * [多次派遣](book/25-Patterns.md#多次派遣)
+ * [访问者模式](book/25-Patterns.md#访问者模式)
+ * [RTTI的优劣](book/25-Patterns.md#RTTI的优劣)
+ * [本章小结](book/25-Patterns.md#本章小结)
+
+### [附录:成为一名程序员](book/Appendix-Becoming-a-Programmer.md)
+ * [如何开始](book/Appendix-Becoming-a-Programmer.md#如何开始)
+ * [码农生涯](book/Appendix-Becoming-a-Programmer.md#码农生涯)
+ * [百分之五的神话](book/Appendix-Becoming-a-Programmer.md#百分之五的神话)
+ * [重在动手](book/Appendix-Becoming-a-Programmer.md#重在动手)
+ * [像打字般编程](book/Appendix-Becoming-a-Programmer.md#像打字般编程)
+ * [做你喜欢的事](book/Appendix-Becoming-a-Programmer.md#做你喜欢的事)
+
+### [附录:静态语言类型检查](book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md)
+ * [前言](book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md#前言)
+ * [静态类型检查和测试](book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md#静态类型检查和测试)
+ * [如何提升打字](book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md#如何提升打字)
+ * [生产力的成本](book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md#生产力的成本)
+ * [静态和动态](book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md#静态和动态)
+
+### [附录:集合主题](book/Appendix-Collection-Topics.md)
+ * [示例数据](book/Appendix-Collection-Topics.md#示例数据)
+ * [List行为](book/Appendix-Collection-Topics.md#List行为)
+ * [Set行为](book/Appendix-Collection-Topics.md#Set行为)
+ * [在Map中使用函数式操作](book/Appendix-Collection-Topics.md#在Map中使用函数式操作)
+ * [选择Map片段](book/Appendix-Collection-Topics.md#选择Map片段)
+ * [填充集合](book/Appendix-Collection-Topics.md#填充集合)
+ * [使用享元(Flyweight)自定义Collection和Map](book/Appendix-Collection-Topics.md#使用享元(Flyweight)自定义Collection和Map)
+ * [集合功能](book/Appendix-Collection-Topics.md#集合功能)
+ * [可选操作](book/Appendix-Collection-Topics.md#可选操作)
+ * [Set和存储顺序](book/Appendix-Collection-Topics.md#Set和存储顺序)
+ * [队列](book/Appendix-Collection-Topics.md#队列)
+ * [理解Map](book/Appendix-Collection-Topics.md#理解Map)
+ * [集合工具类](book/Appendix-Collection-Topics.md#集合工具类)
+ * [持有引用](book/Appendix-Collection-Topics.md#持有引用)
+ * [Java 1.0 / 1.1 的集合类](book/Appendix-Collection-Topics.md#Java-10-11-的集合类)
+ * [本章小结](book/Appendix-Collection-Topics.md#本章小结)
+
+### [附录:数据压缩](book/Appendix-Data-Compression.md)
+ * [使用 Gzip 简单压缩](book/Appendix-Data-Compression.md#使用-Gzip-简单压缩)
+ * [使用 zip 多文件存储](book/Appendix-Data-Compression.md#使用-zip-多文件存储)
+ * [Java 的 jar](book/Appendix-Data-Compression.md#Java-的-jar)
+
+### [附录:流式IO](book/Appendix-IO-Streams.md)
+ * [输入流类型](book/Appendix-IO-Streams.md#输入流类型)
+ * [输出流类型](book/Appendix-IO-Streams.md#输出流类型)
+ * [添加属性和有用的接口](book/Appendix-IO-Streams.md#添加属性和有用的接口)
+ * [Reader和Writer](book/Appendix-IO-Streams.md#Reader和Writer)
+ * [RandomAccessFile类](book/Appendix-IO-Streams.md#RandomAccessFile类)
+ * [IO流典型用途](book/Appendix-IO-Streams.md#IO流典型用途)
+ * [本章小结](book/Appendix-IO-Streams.md#本章小结)
+
+### [附录:文档注释](book/Appendix-Javadoc.md)
+ * [句法规则](book/Appendix-Javadoc.md#句法规则)
+ * [内嵌 HTML](book/Appendix-Javadoc.md#内嵌-HTML)
+ * [示例标签](book/Appendix-Javadoc.md#示例标签)
+ * [文档示例](book/Appendix-Javadoc.md#文档示例)
+
+### [附录:并发底层原理](book/Appendix-Low-Level-Concurrency.md)
+ * [什么是线程?](book/Appendix-Low-Level-Concurrency.md#什么是线程?)
+ * [异常捕获](book/Appendix-Low-Level-Concurrency.md#异常捕获)
+ * [资源共享](book/Appendix-Low-Level-Concurrency.md#资源共享)
+ * [volatile 关键字](book/Appendix-Low-Level-Concurrency.md#volatile-关键字)
+ * [原子性](book/Appendix-Low-Level-Concurrency.md#原子性)
+ * [临界区](book/Appendix-Low-Level-Concurrency.md#临界区)
+ * [库组件](book/Appendix-Low-Level-Concurrency.md#库组件)
+ * [本章小结](book/Appendix-Low-Level-Concurrency.md#本章小结)
+
+### [附录:新IO](book/Appendix-New-IO.md)
+ * [ByteBuffer](book/Appendix-New-IO.md#ByteBuffer)
+ * [数据转换](book/Appendix-New-IO.md#数据转换)
+ * [基本类型获取](book/Appendix-New-IO.md#基本类型获取)
+ * [视图缓冲区](book/Appendix-New-IO.md#视图缓冲区)
+ * [缓冲区数据操作](book/Appendix-New-IO.md#缓冲区数据操作)
+ * [ 内存映射文件](book/Appendix-New-IO.md#-内存映射文件)
+ * [文件锁定](book/Appendix-New-IO.md#文件锁定)
+
+### [附录:对象序列化](book/Appendix-Object-Serialization.md)
+ * [查找类](book/Appendix-Object-Serialization.md#查找类)
+ * [控制序列化](book/Appendix-Object-Serialization.md#控制序列化)
+ * [使用持久化](book/Appendix-Object-Serialization.md#使用持久化)
+ * [XML](book/Appendix-Object-Serialization.md#XML)
+
+### [附录:对象传递和返回](book/Appendix-Passing-and-Returning-Objects.md)
+ * [传递引用](book/Appendix-Passing-and-Returning-Objects.md#传递引用)
+ * [本地拷贝](book/Appendix-Passing-and-Returning-Objects.md#本地拷贝)
+ * [控制克隆](book/Appendix-Passing-and-Returning-Objects.md#控制克隆)
+ * [不可变类](book/Appendix-Passing-and-Returning-Objects.md#不可变类)
+ * [本章小结](book/Appendix-Passing-and-Returning-Objects.md#本章小结)
+
+### [附录:编程指南](book/Appendix-Programming-Guidelines.md)
+ * [设计](book/Appendix-Programming-Guidelines.md#设计)
+ * [实现](book/Appendix-Programming-Guidelines.md#实现)
+
+### [附录:标准IO](book/Appendix-Standard-IO.md)
+ * [从标准输入中读取](book/Appendix-Standard-IO.md#从标准输入中读取)
+ * [将 System.out 转换成 PrintWriter](book/Appendix-Standard-IO.md#将-Systemout-转换成-PrintWriter)
+ * [重定向标准 I/O](book/Appendix-Standard-IO.md#重定向标准-IO)
+ * [执行控制](book/Appendix-Standard-IO.md#执行控制)
+
+### [附录:补充](book/Appendix-Supplements.md)
+ * [可下载的补充](book/Appendix-Supplements.md#可下载的补充)
+ * [通过Thinking-in-C来巩固Java基础](book/Appendix-Supplements.md#通过Thinking-in-C来巩固Java基础)
+ * [Hand-On Java 电子演示文稿](book/Appendix-Supplements.md#Hand-On-Java-电子演示文稿)
+
+### [附录:C++和Java的优良传统](book/Appendix-The-Positive-Legacy-of-C-plus-plus-and-Java.md)
+
+### [附录:理解equals和hashCode方法](book/Appendix-Understanding-equals-and-hashCode.md)
+ * [equals规范](book/Appendix-Understanding-equals-and-hashCode.md#equals规范)
+ * [哈希和哈希码](book/Appendix-Understanding-equals-and-hashCode.md#哈希和哈希码)
+ * [调优 HashMap](book/Appendix-Understanding-equals-and-hashCode.md#调优-HashMap)
+
+### [词汇表](book/GLOSSARY.md)
\ No newline at end of file
diff --git a/docs/book/05-Control-Flow.md b/docs/book/05-Control-Flow.md
old mode 100644
new mode 100755
index 854d6dc5..c12ac689
--- a/docs/book/05-Control-Flow.md
+++ b/docs/book/05-Control-Flow.md
@@ -235,7 +235,7 @@ i = 4 j = 8
上例中 **int** 类型声明包含了 `i` 和 `j`。实际上,在初始化部分我们可以定义任意数量的同类型变量。**注意**:在 Java 中,仅允许 **for** 循环在控制表达式中定义变量。 我们不能将此方法与其他的循环语句和选择语句中一起使用。同时,我们可以看到:无论在初始化还是在步进部分,语句都是顺序执行的。
-## for-in 语法
+## for-in 语法
Java 5 引入了更为简洁的“增强版 **for** 循环”语法来操纵数组和集合。(更多细节,可参考 [数组](./21-Arrays.md) 和 [集合](./12-Collections.md) 章节内容)。大部分文档也称其为 **for-each** 语法,但因为了不与 Java 8 新添的 `forEach()` 产生混淆,因此我称之为 **for-in** 循环。 (Python 已有类似的先例,如:**for x in sequence**)。**注意**:你可能会在其他地方看到不同叫法。
diff --git a/docs/book/11-Inner-Classes.md b/docs/book/11-Inner-Classes.md
old mode 100644
new mode 100755
diff --git a/docs/book/18-Strings.md b/docs/book/18-Strings.md
old mode 100644
new mode 100755
index be0bca0b..0b7bc7e5
--- a/docs/book/18-Strings.md
+++ b/docs/book/18-Strings.md
@@ -47,7 +47,7 @@ String x = Immutable.upcase(s);
-## `+` 的重载与 `StringBuilder`
+## + 的重载与 StringBuilder
`String` 对象是不可变的,你可以给一个 `String` 对象添加任意多的别名。因为 `String` 是只读的,所以指向它的任何引用都不可能修改它的值,因此,也就不会影响到其他引用。
不可变性会带来一定的效率问题。为 `String` 对象重载的 `+` 操作符就是一个例子。重载的意思是,一个操作符在用于特定的类时,被赋予了特殊的意义(用于 `String` 的 `+` 与 `+=` 是 Java 中仅有的两个重载过的操作符,Java 不允许程序员重载任何其他的操作符 [^1])。
diff --git a/docs/book/19-Type-Information.md b/docs/book/19-Type-Information.md
old mode 100644
new mode 100755
index f013b51a..6c51d949
--- a/docs/book/19-Type-Information.md
+++ b/docs/book/19-Type-Information.md
@@ -84,7 +84,7 @@ Triangle.draw()
但是,有时你会碰到一些编程问题,在这些问题中如果你能知道某个泛化引用的具体类型,就可以把问题轻松解决。例如,假设我们允许用户将某些几何形状高亮显示,现在希望找到屏幕上所有高亮显示的三角形;或者,我们现在需要旋转所有图形,但是想跳过圆形(因为圆形旋转没有意义)。这时我们就希望知道 `Stream` 里边的形状具体是什么类型,而 Java 实际上也满足了我们的这种需求。使用 RTTI,我们可以查询某个 `Shape` 引用所指向对象的确切类型,然后选择或者剔除特例。
-## `Class` 对象
+## Class 对象
要理解 RTTI 在 Java 中的工作原理,首先必须知道类型信息在运行时是如何表示的。这项工作是由称为 **`Class`对象** 的特殊对象完成的,它包含了与类有关的信息。实际上,`Class` 对象就是用来创建该类所有"常规"对象的。Java 使用 `Class` 对象来实现 RTTI,即便是类型转换这样的操作都是用 `Class` 对象实现的。不仅如此,`Class` 类还提供了很多使用 RTTI 的其它方式。
diff --git a/docs/book/21-Arrays.md b/docs/book/21-Arrays.md
old mode 100644
new mode 100755
index 0ff7dad6..979170cf
--- a/docs/book/21-Arrays.md
+++ b/docs/book/21-Arrays.md
@@ -2414,7 +2414,7 @@ After sorting: [[i = 21, j = 6], [i = 70, j = 7], [i = 41, j = 20] ,
```
-## Arrays.sort()的使用
+## Arrays.sort 的使用
使用内置的排序方法,您可以对实现了 **Comparable** 接口或具有 **Comparator** 的任何对象数组 或 任何原生数组进行排序。这里我们生成一个随机字符串对象数组并对其排序:
diff --git a/docs/book/24-Concurrent-Programming.md b/docs/book/24-Concurrent-Programming.md
old mode 100644
new mode 100755
index 603eb9e9..9046c59c
--- a/docs/book/24-Concurrent-Programming.md
+++ b/docs/book/24-Concurrent-Programming.md
@@ -221,7 +221,7 @@ Java采用了更传统的方法[^2],即在顺序语言之上添加对线程的
Java是一种多线程语言,不管你有没有意识到并发问题,它就在那里。因此,有许多Java程序正在使用中,或者只是偶然工作,或者大部分时间工作并且不时地发生问题,因为。有时这种问题是相对良性的,但有时它意味着丢失有价值的数据,如果你没有意识到并发问题,你最终可能会把问题放在其他地方而不是你的代码中。如果将程序移动到多处理器系统,则可以暴露或放大这些类型的问题。基本上,了解并发性使你意识到正确的程序可能会表现出错误的行为。
-## 残酷的真相
+## 残酷的真相
当人类开始烹饪他们的食物时,他们大大减少了他们的身体分解和消化食物所需的能量。烹饪创造了一个“外化的胃”,从而释放出能量去发展其他的能力。火的使用促成了文明。
diff --git a/docs/book/Appendix-Standard-IO.md b/docs/book/Appendix-Standard-IO.md
old mode 100644
new mode 100755
index bfc6d597..842e2804
--- a/docs/book/Appendix-Standard-IO.md
+++ b/docs/book/Appendix-Standard-IO.md
@@ -35,7 +35,7 @@ public class Echo {
`BufferedReader` 提供了 `lines()` 方法,返回类型是 `Stream` 。这显示出流模型的的灵活性:仅使用标准输入就能很好地工作。 `peek()` 方法重启 `TimeAbort`,只要保证至少每隔两秒有输入就能够使程序保持开启状态。
-## 将`System.out` 转换成 `PrintWriter`
+## 将 System.out 转换成 PrintWriter
`System.out` 是一个 `PrintStream`,而 `PrintStream` 是一个`OutputStream`。 `PrintWriter` 有一个把 `OutputStream` 作为参数的构造器。因此,如果你需要的话,可以使用这个构造器把 `System.out` 转换成 `PrintWriter` 。
diff --git a/docs/index.html b/docs/index.html
old mode 100644
new mode 100755
index b7e41098..a19f3ccd
--- a/docs/index.html
+++ b/docs/index.html
@@ -352,22 +352,22 @@
repo: 'https://github.com/LingCoder/OnJava8',
loadSidebar: 'sidebar.md',
// subMaxLevel: 3,
- search: {
- paths: 'auto',
- placeholder: '🔍 点击搜索 ',
- noData: '😞 没有结果! ',
- // Headline depth, 1 - 6
- depth: 6
- },
- copyCode: {
- buttonText : '复制',
- errorText : 'Error',
- successText: 'OK!'
- },
- pagination: {
- previousText: '上一章节',
- nextText: '下一章节',
- },
+ search: {
+ paths: 'auto',
+ placeholder: '🔍 点击搜索 ',
+ noData: '😞 没有结果! ',
+ // Headline depth, 1 - 6
+ depth: 6
+ },
+ copyCode: {
+ buttonText : '复制',
+ errorText : 'Error',
+ successText: 'OK!'
+ },
+ pagination: {
+ previousText: '上一章节',
+ nextText: '下一章节',
+ },
coverpage: true,
}
diff --git a/docs/sidebar.md b/docs/sidebar.md
index dbde9004..5f2b8733 100644
--- a/docs/sidebar.md
+++ b/docs/sidebar.md
@@ -1,4 +1,5 @@
+
### [译者的话](README.md)
### [封面](book/00-On-Java-8.md)
@@ -15,9 +16,9 @@
* [复用](book/01-What-is-an-Object.md#复用)
* [继承](book/01-What-is-an-Object.md#继承)
* [多态](book/01-What-is-an-Object.md#多态)
- * [单继承](book/01-What-is-an-Object.md#单继承)
+ * [单继承结构](book/01-What-is-an-Object.md#单继承结构)
* [集合](book/01-What-is-an-Object.md#集合)
- * [生命周期](book/01-What-is-an-Object.md#生命周期)
+ * [对象创建与生命周期](book/01-What-is-an-Object.md#对象创建与生命周期)
* [异常处理](book/01-What-is-an-Object.md#异常处理)
* [本章小结](book/01-What-is-an-Object.md#本章小结)
@@ -48,7 +49,7 @@
* [关系运算符](book/04-Operators.md#关系运算符)
* [逻辑运算符](book/04-Operators.md#逻辑运算符)
* [字面值常量](book/04-Operators.md#字面值常量)
- * [按位运算符](book/04-Operators.md#按位运算符)
+ * [位运算符](book/04-Operators.md#位运算符)
* [移位运算符](book/04-Operators.md#移位运算符)
* [三元运算符](book/04-Operators.md#三元运算符)
* [字符串运算符](book/04-Operators.md#字符串运算符)
@@ -59,15 +60,15 @@
* [本章小结](book/04-Operators.md#本章小结)
### [第五章 控制流](book/05-Control-Flow.md)
- * [true和flase](book/05-Control-Flow.md#true和flase)
+ * [true和false](book/05-Control-Flow.md#true和false)
* [if-else](book/05-Control-Flow.md#if-else)
* [迭代语句](book/05-Control-Flow.md#迭代语句)
- * [for-in语法](book/05-Control-Flow.md#for-in语法)
+ * [for-in 语法](book/05-Control-Flow.md#for-in-语法)
* [return](book/05-Control-Flow.md#return)
- * [break和continue](book/05-Control-Flow.md#break和continue)
- * [臭名昭著的goto](book/05-Control-Flow.md#臭名昭著的goto)
+ * [break 和 continue](book/05-Control-Flow.md#break-和-continue)
+ * [臭名昭著的 goto](book/05-Control-Flow.md#臭名昭著的-goto)
* [switch](book/05-Control-Flow.md#switch)
- * [switch字符串](book/05-Control-Flow.md#switch字符串)
+ * [switch 字符串](book/05-Control-Flow.md#switch-字符串)
* [本章小结](book/05-Control-Flow.md#本章小结)
### [第六章 初始化和清理](book/06-Housekeeping.md)
@@ -102,10 +103,10 @@
* [本章小结](book/08-Reuse.md#本章小结)
### [第九章 多态](book/09-Polymorphism.md)
- * [向上转型回溯](book/09-Polymorphism.md#向上转型回溯)
- * [深入理解](book/09-Polymorphism.md#深入理解)
+ * [向上转型回顾](book/09-Polymorphism.md#向上转型回顾)
+ * [转机](book/09-Polymorphism.md#转机)
* [构造器和多态](book/09-Polymorphism.md#构造器和多态)
- * [返回类型协变](book/09-Polymorphism.md#返回类型协变)
+ * [协变返回类型](book/09-Polymorphism.md#协变返回类型)
* [使用继承设计](book/09-Polymorphism.md#使用继承设计)
* [本章小结](book/09-Polymorphism.md#本章小结)
@@ -125,15 +126,15 @@
### [第十一章 内部类](book/11-Inner-Classes.md)
* [创建内部类](book/11-Inner-Classes.md#创建内部类)
* [链接外部类](book/11-Inner-Classes.md#链接外部类)
- * [内部类this和new的使用](book/11-Inner-Classes.md#内部类this和new的使用)
- * [内部类向上转型](book/11-Inner-Classes.md#内部类向上转型)
+ * [使用 .this 和 .new](book/11-Inner-Classes.md#使用-this-和-new)
+ * [内部类与向上转型](book/11-Inner-Classes.md#内部类与向上转型)
* [内部类方法和作用域](book/11-Inner-Classes.md#内部类方法和作用域)
* [匿名内部类](book/11-Inner-Classes.md#匿名内部类)
* [嵌套类](book/11-Inner-Classes.md#嵌套类)
* [为什么需要内部类](book/11-Inner-Classes.md#为什么需要内部类)
* [继承内部类](book/11-Inner-Classes.md#继承内部类)
- * [重写内部类](book/11-Inner-Classes.md#重写内部类)
- * [内部类局部变量](book/11-Inner-Classes.md#内部类局部变量)
+ * [内部类可以被覆盖么?](book/11-Inner-Classes.md#内部类可以被覆盖么?)
+ * [局部内部类](book/11-Inner-Classes.md#局部内部类)
* [内部类标识符](book/11-Inner-Classes.md#内部类标识符)
* [本章小结](book/11-Inner-Classes.md#本章小结)
@@ -178,26 +179,27 @@
* [基本异常](book/15-Exceptions.md#基本异常)
* [异常捕获](book/15-Exceptions.md#异常捕获)
* [自定义异常](book/15-Exceptions.md#自定义异常)
- * [异常规范](book/15-Exceptions.md#异常规范)
- * [任意异常捕获](book/15-Exceptions.md#任意异常捕获)
- * [Java标准异常](book/15-Exceptions.md#Java标准异常)
- * [finally关键字](book/15-Exceptions.md#finally关键字)
+ * [异常声明](book/15-Exceptions.md#异常声明)
+ * [捕获所有异常](book/15-Exceptions.md#捕获所有异常)
+ * [Java 标准异常](book/15-Exceptions.md#Java-标准异常)
+ * [使用 finally 进行清理](book/15-Exceptions.md#使用-finally-进行清理)
* [异常限制](book/15-Exceptions.md#异常限制)
- * [异常构造](book/15-Exceptions.md#异常构造)
- * [Try-With-Resources用法](book/15-Exceptions.md#Try-With-Resources用法)
+ * [构造器](book/15-Exceptions.md#构造器)
+ * [Try-With-Resources 用法](book/15-Exceptions.md#Try-With-Resources-用法)
* [异常匹配](book/15-Exceptions.md#异常匹配)
- * [异常准则](book/15-Exceptions.md#异常准则)
+ * [其他可选方式](book/15-Exceptions.md#其他可选方式)
* [异常指南](book/15-Exceptions.md#异常指南)
* [本章小结](book/15-Exceptions.md#本章小结)
+ * [后记:Exception Bizarro World](book/15-Exceptions.md#后记:Exception-Bizarro-World)
### [第十六章 代码校验](book/16-Validating-Your-Code.md)
* [测试](book/16-Validating-Your-Code.md#测试)
- * [前提条件](book/16-Validating-Your-Code.md#前提条件)
+ * [前置条件](book/16-Validating-Your-Code.md#前置条件)
* [测试驱动开发](book/16-Validating-Your-Code.md#测试驱动开发)
* [日志](book/16-Validating-Your-Code.md#日志)
* [调试](book/16-Validating-Your-Code.md#调试)
* [基准测试](book/16-Validating-Your-Code.md#基准测试)
- * [分析和优化](book/16-Validating-Your-Code.md#分析和优化)
+ * [剖析和优化](book/16-Validating-Your-Code.md#剖析和优化)
* [风格检测](book/16-Validating-Your-Code.md#风格检测)
* [静态错误分析](book/16-Validating-Your-Code.md#静态错误分析)
* [代码重审](book/16-Validating-Your-Code.md#代码重审)
@@ -217,22 +219,22 @@
### [第十八章 字符串](book/18-Strings.md)
* [字符串的不可变](book/18-Strings.md#字符串的不可变)
- * [重载和StringBuilder](book/18-Strings.md#重载和StringBuilder)
+ * [+ 的重载与 StringBuilder](book/18-Strings.md#+-的重载与-StringBuilder)
* [意外递归](book/18-Strings.md#意外递归)
* [字符串操作](book/18-Strings.md#字符串操作)
* [格式化输出](book/18-Strings.md#格式化输出)
- * [常规表达式](book/18-Strings.md#常规表达式)
+ * [正则表达式](book/18-Strings.md#正则表达式)
* [扫描输入](book/18-Strings.md#扫描输入)
* [StringTokenizer类](book/18-Strings.md#StringTokenizer类)
* [本章小结](book/18-Strings.md#本章小结)
### [第十九章 类型信息](book/19-Type-Information.md)
- * [运行时类型信息](book/19-Type-Information.md#运行时类型信息)
- * [类的对象](book/19-Type-Information.md#类的对象)
+ * [为什么需要 RTTI](book/19-Type-Information.md#为什么需要-RTTI)
+ * [Class 对象](book/19-Type-Information.md#Class-对象)
* [类型转换检测](book/19-Type-Information.md#类型转换检测)
* [注册工厂](book/19-Type-Information.md#注册工厂)
* [类的等价比较](book/19-Type-Information.md#类的等价比较)
- * [反射运行时类信息](book/19-Type-Information.md#反射运行时类信息)
+ * [反射:运行时类信息](book/19-Type-Information.md#反射:运行时类信息)
* [动态代理](book/19-Type-Information.md#动态代理)
* [Optional类](book/19-Type-Information.md#Optional类)
* [接口和类型](book/19-Type-Information.md#接口和类型)
@@ -242,20 +244,21 @@
* [简单泛型](book/20-Generics.md#简单泛型)
* [泛型接口](book/20-Generics.md#泛型接口)
* [泛型方法](book/20-Generics.md#泛型方法)
- * [复杂模型构建](book/20-Generics.md#复杂模型构建)
+ * [构建复杂模型](book/20-Generics.md#构建复杂模型)
* [泛型擦除](book/20-Generics.md#泛型擦除)
* [补偿擦除](book/20-Generics.md#补偿擦除)
* [边界](book/20-Generics.md#边界)
* [通配符](book/20-Generics.md#通配符)
* [问题](book/20-Generics.md#问题)
- * [自我约束类型](book/20-Generics.md#自我约束类型)
+ * [自限定的类型](book/20-Generics.md#自限定的类型)
* [动态类型安全](book/20-Generics.md#动态类型安全)
* [泛型异常](book/20-Generics.md#泛型异常)
- * [混入](book/20-Generics.md#混入)
- * [潜在类型](book/20-Generics.md#潜在类型)
- * [补偿不足](book/20-Generics.md#补偿不足)
- * [辅助潜在类型](book/20-Generics.md#辅助潜在类型)
- * [泛型的优劣](book/20-Generics.md#泛型的优劣)
+ * [混型](book/20-Generics.md#混型)
+ * [潜在类型机制](book/20-Generics.md#潜在类型机制)
+ * [对缺乏潜在类型机制的补偿](book/20-Generics.md#对缺乏潜在类型机制的补偿)
+ * [Java8 中的辅助潜在类型](book/20-Generics.md#Java8-中的辅助潜在类型)
+ * [总结:类型转换真的如此之糟吗?](book/20-Generics.md#总结:类型转换真的如此之糟吗?)
+ * [进阶阅读](book/20-Generics.md#进阶阅读)
### [第二十一章 数组](book/21-Arrays.md)
* [数组特性](book/21-Arrays.md#数组特性)
@@ -275,22 +278,24 @@
* [数组比较](book/21-Arrays.md#数组比较)
* [流和数组](book/21-Arrays.md#流和数组)
* [数组排序](book/21-Arrays.md#数组排序)
+ * [Arrays.sort 的使用](book/21-Arrays.md#Arrayssort-的使用)
+ * [并行排序](book/21-Arrays.md#并行排序)
* [binarySearch二分查找](book/21-Arrays.md#binarySearch二分查找)
* [parallelPrefix并行前缀](book/21-Arrays.md#parallelPrefix并行前缀)
* [本章小结](book/21-Arrays.md#本章小结)
### [第二十二章 枚举](book/22-Enumerations.md)
- * [基本功能](book/22-Enumerations.md#基本功能)
+ * [基本 enum 特性](book/22-Enumerations.md#基本-enum-特性)
* [方法添加](book/22-Enumerations.md#方法添加)
- * [switch语句](book/22-Enumerations.md#switch语句)
- * [values方法](book/22-Enumerations.md#values方法)
+ * [switch 语句中的 enum](book/22-Enumerations.md#switch-语句中的-enum)
+ * [values 方法的神秘之处](book/22-Enumerations.md#values-方法的神秘之处)
* [实现而非继承](book/22-Enumerations.md#实现而非继承)
* [随机选择](book/22-Enumerations.md#随机选择)
- * [使用接口组织](book/22-Enumerations.md#使用接口组织)
- * [使用EnumSet替代Flags](book/22-Enumerations.md#使用EnumSet替代Flags)
- * [使用EnumMap](book/22-Enumerations.md#使用EnumMap)
+ * [使用接口组织枚举](book/22-Enumerations.md#使用接口组织枚举)
+ * [使用 EnumSet 替代 Flags](book/22-Enumerations.md#使用-EnumSet-替代-Flags)
+ * [使用 EnumMap](book/22-Enumerations.md#使用-EnumMap)
* [常量特定方法](book/22-Enumerations.md#常量特定方法)
- * [多次调度](book/22-Enumerations.md#多次调度)
+ * [多路分发](book/22-Enumerations.md#多路分发)
* [本章小结](book/22-Enumerations.md#本章小结)
### [第二十三章 注解](book/23-Annotations.md)
@@ -303,7 +308,7 @@
### [第二十四章 并发编程](book/24-Concurrent-Programming.md)
* [术语问题](book/24-Concurrent-Programming.md#术语问题)
* [并发的超能力](book/24-Concurrent-Programming.md#并发的超能力)
- * [针对速度](book/24-Concurrent-Programming.md#针对速度)
+ * [并发为速度而生](book/24-Concurrent-Programming.md#并发为速度而生)
* [四句格言](book/24-Concurrent-Programming.md#四句格言)
* [残酷的真相](book/24-Concurrent-Programming.md#残酷的真相)
* [本章其余部分](book/24-Concurrent-Programming.md#本章其余部分)
@@ -312,18 +317,18 @@
* [终止耗时任务](book/24-Concurrent-Programming.md#终止耗时任务)
* [CompletableFuture类](book/24-Concurrent-Programming.md#CompletableFuture类)
* [死锁](book/24-Concurrent-Programming.md#死锁)
- * [构造函数非线程安全](book/24-Concurrent-Programming.md#构造函数非线程安全)
+ * [构造方法非线程安全](book/24-Concurrent-Programming.md#构造方法非线程安全)
* [复杂性和代价](book/24-Concurrent-Programming.md#复杂性和代价)
* [本章小结](book/24-Concurrent-Programming.md#本章小结)
### [第二十五章 设计模式](book/25-Patterns.md)
* [概念](book/25-Patterns.md#概念)
- * [构建型](book/25-Patterns.md#构建型)
- * [面向实施](book/25-Patterns.md#面向实施)
+ * [构建应用程序框架](book/25-Patterns.md#构建应用程序框架)
+ * [面向实现](book/25-Patterns.md#面向实现)
* [工厂模式](book/25-Patterns.md#工厂模式)
* [函数对象](book/25-Patterns.md#函数对象)
- * [接口改变](book/25-Patterns.md#接口改变)
- * [解释器](book/25-Patterns.md#解释器)
+ * [改变接口](book/25-Patterns.md#改变接口)
+ * [解释器:运行时的弹性](book/25-Patterns.md#解释器:运行时的弹性)
* [回调](book/25-Patterns.md#回调)
* [多次调度](book/25-Patterns.md#多次调度)
* [模式重构](book/25-Patterns.md#模式重构)
@@ -333,58 +338,29 @@
* [RTTI的优劣](book/25-Patterns.md#RTTI的优劣)
* [本章小结](book/25-Patterns.md#本章小结)
-### [附录:补充](book/Appendix-Supplements.md)
- * [可下载的补充](book/Appendix-Supplements.md#可下载的补充)
- * [通过Thinking-in-C来巩固Java基础](book/Appendix-Supplements.md#通过Thinking-in-C来巩固Java基础)
- * [动手实践](book/Appendix-Supplements.md#动手实践)
-
-### [附录:编程指南](book/Appendix-Programming-Guidelines.md)
- * [设计](book/Appendix-Programming-Guidelines.md#设计)
- * [实现](book/Appendix-Programming-Guidelines.md#实现)
-
-### [附录:文档注释](book/Appendix-Javadoc.md)
-
-### [附录:对象传递和返回](book/Appendix-Passing-and-Returning-Objects.md)
- * [传递引用](book/Appendix-Passing-and-Returning-Objects.md#传递引用)
- * [本地拷贝](book/Appendix-Passing-and-Returning-Objects.md#本地拷贝)
- * [控制克隆](book/Appendix-Passing-and-Returning-Objects.md#控制克隆)
- * [不可变类](book/Appendix-Passing-and-Returning-Objects.md#不可变类)
- * [本章小结](book/Appendix-Passing-and-Returning-Objects.md#本章小结)
-
-### [附录:流式IO](book/Appendix-IO-Streams.md)
- * [输入流类型](book/Appendix-IO-Streams.md#输入流类型)
- * [输出流类型](book/Appendix-IO-Streams.md#输出流类型)
- * [添加属性和有用的接口](book/Appendix-IO-Streams.md#添加属性和有用的接口)
- * [Reader和Writer](book/Appendix-IO-Streams.md#Reader和Writer)
- * [RandomAccessFile类](book/Appendix-IO-Streams.md#RandomAccessFile类)
- * [IO流典型用途](book/Appendix-IO-Streams.md#IO流典型用途)
- * [本章小结](book/Appendix-IO-Streams.md#本章小结)
-
-### [附录:标准IO](book/Appendix-Standard-IO.md)
- * [执行控制](book/Appendix-Standard-IO.md#执行控制)
-
-### [附录:新IO](book/Appendix-New-IO.md)
- * [ByteBuffer](book/Appendix-New-IO.md#ByteBuffer)
- * [转换数据](book/Appendix-New-IO.md#数据转换)
- * [获取原始类型](book/Appendix-New-IO.md#基本类型获取)
- * [视图缓冲区](book/Appendix-New-IO.md#视图缓冲区)
- * [使用缓冲区进行数据操作](book/Appendix-New-IO.md#缓冲区数据操作)
- * [内存映射文件](book/Appendix-New-IO.md#内存映射文件)
- * [文件锁定](book/Appendix-New-IO.md#文件锁定)
+### [附录:成为一名程序员](book/Appendix-Becoming-a-Programmer.md)
+ * [如何开始](book/Appendix-Becoming-a-Programmer.md#如何开始)
+ * [码农生涯](book/Appendix-Becoming-a-Programmer.md#码农生涯)
+ * [百分之五的神话](book/Appendix-Becoming-a-Programmer.md#百分之五的神话)
+ * [重在动手](book/Appendix-Becoming-a-Programmer.md#重在动手)
+ * [像打字般编程](book/Appendix-Becoming-a-Programmer.md#像打字般编程)
+ * [做你喜欢的事](book/Appendix-Becoming-a-Programmer.md#做你喜欢的事)
-### [附录:理解equals和hashCode方法](book/Appendix-Understanding-equals-and-hashCode.md)
- * [equals典范](book/Appendix-Understanding-equals-and-hashCode.md#equals典范)
- * [哈希和哈希码](book/Appendix-Understanding-equals-and-hashCode.md#哈希和哈希码)
- * [调整HashMap](book/Appendix-Understanding-equals-and-hashCode.md#调整HashMap)
+### [附录:静态语言类型检查](book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md)
+ * [前言](book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md#前言)
+ * [静态类型检查和测试](book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md#静态类型检查和测试)
+ * [如何提升打字](book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md#如何提升打字)
+ * [生产力的成本](book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md#生产力的成本)
+ * [静态和动态](book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md#静态和动态)
### [附录:集合主题](book/Appendix-Collection-Topics.md)
* [示例数据](book/Appendix-Collection-Topics.md#示例数据)
- * [List表现](book/Appendix-Collection-Topics.md#List表现)
- * [Set表现](book/Appendix-Collection-Topics.md#Set表现)
+ * [List行为](book/Appendix-Collection-Topics.md#List行为)
+ * [Set行为](book/Appendix-Collection-Topics.md#Set行为)
* [在Map中使用函数式操作](book/Appendix-Collection-Topics.md#在Map中使用函数式操作)
- * [选择Map的部分](book/Appendix-Collection-Topics.md#选择Map的部分)
- * [集合的fill方法](book/Appendix-Collection-Topics.md#集合的fill方法)
- * [使用Flyweight自定义集合和Map](book/Appendix-Collection-Topics.md#使用Flyweight自定义集合和Map)
+ * [选择Map片段](book/Appendix-Collection-Topics.md#选择Map片段)
+ * [填充集合](book/Appendix-Collection-Topics.md#填充集合)
+ * [使用享元(Flyweight)自定义Collection和Map](book/Appendix-Collection-Topics.md#使用享元(Flyweight)自定义Collection和Map)
* [集合功能](book/Appendix-Collection-Topics.md#集合功能)
* [可选操作](book/Appendix-Collection-Topics.md#可选操作)
* [Set和存储顺序](book/Appendix-Collection-Topics.md#Set和存储顺序)
@@ -392,44 +368,81 @@
* [理解Map](book/Appendix-Collection-Topics.md#理解Map)
* [集合工具类](book/Appendix-Collection-Topics.md#集合工具类)
* [持有引用](book/Appendix-Collection-Topics.md#持有引用)
- * [避免旧式类库](book/Appendix-Collection-Topics.md#避免旧式类库)
+ * [Java 1.0 / 1.1 的集合类](book/Appendix-Collection-Topics.md#Java-10-11-的集合类)
* [本章小结](book/Appendix-Collection-Topics.md#本章小结)
+### [附录:数据压缩](book/Appendix-Data-Compression.md)
+ * [使用 Gzip 简单压缩](book/Appendix-Data-Compression.md#使用-Gzip-简单压缩)
+ * [使用 zip 多文件存储](book/Appendix-Data-Compression.md#使用-zip-多文件存储)
+ * [Java 的 jar](book/Appendix-Data-Compression.md#Java-的-jar)
+
+### [附录:流式IO](book/Appendix-IO-Streams.md)
+ * [输入流类型](book/Appendix-IO-Streams.md#输入流类型)
+ * [输出流类型](book/Appendix-IO-Streams.md#输出流类型)
+ * [添加属性和有用的接口](book/Appendix-IO-Streams.md#添加属性和有用的接口)
+ * [Reader和Writer](book/Appendix-IO-Streams.md#Reader和Writer)
+ * [RandomAccessFile类](book/Appendix-IO-Streams.md#RandomAccessFile类)
+ * [IO流典型用途](book/Appendix-IO-Streams.md#IO流典型用途)
+ * [本章小结](book/Appendix-IO-Streams.md#本章小结)
+
+### [附录:文档注释](book/Appendix-Javadoc.md)
+ * [句法规则](book/Appendix-Javadoc.md#句法规则)
+ * [内嵌 HTML](book/Appendix-Javadoc.md#内嵌-HTML)
+ * [示例标签](book/Appendix-Javadoc.md#示例标签)
+ * [文档示例](book/Appendix-Javadoc.md#文档示例)
+
### [附录:并发底层原理](book/Appendix-Low-Level-Concurrency.md)
- * [线程](book/Appendix-Low-Level-Concurrency.md#线程)
+ * [什么是线程?](book/Appendix-Low-Level-Concurrency.md#什么是线程?)
* [异常捕获](book/Appendix-Low-Level-Concurrency.md#异常捕获)
* [资源共享](book/Appendix-Low-Level-Concurrency.md#资源共享)
- * [volatile关键字](book/Appendix-Low-Level-Concurrency.md#volatile关键字)
+ * [volatile 关键字](book/Appendix-Low-Level-Concurrency.md#volatile-关键字)
* [原子性](book/Appendix-Low-Level-Concurrency.md#原子性)
- * [关键部分](book/Appendix-Low-Level-Concurrency.md#关键部分)
+ * [临界区](book/Appendix-Low-Level-Concurrency.md#临界区)
* [库组件](book/Appendix-Low-Level-Concurrency.md#库组件)
* [本章小结](book/Appendix-Low-Level-Concurrency.md#本章小结)
-### [附录:数据压缩](book/Appendix-Data-Compression.md)
- * [使用Gzip简单压缩](book/Appendix-Data-Compression.md#使用Gzip简单压缩)
- * [使用zip多文件存储](book/Appendix-Data-Compression.md#使用zip多文件存储)
- * [Java的jar](book/Appendix-Data-Compression.md#Java的jar)
+### [附录:新IO](book/Appendix-New-IO.md)
+ * [ByteBuffer](book/Appendix-New-IO.md#ByteBuffer)
+ * [数据转换](book/Appendix-New-IO.md#数据转换)
+ * [基本类型获取](book/Appendix-New-IO.md#基本类型获取)
+ * [视图缓冲区](book/Appendix-New-IO.md#视图缓冲区)
+ * [缓冲区数据操作](book/Appendix-New-IO.md#缓冲区数据操作)
+ * [ 内存映射文件](book/Appendix-New-IO.md#-内存映射文件)
+ * [文件锁定](book/Appendix-New-IO.md#文件锁定)
### [附录:对象序列化](book/Appendix-Object-Serialization.md)
* [查找类](book/Appendix-Object-Serialization.md#查找类)
* [控制序列化](book/Appendix-Object-Serialization.md#控制序列化)
* [使用持久化](book/Appendix-Object-Serialization.md#使用持久化)
+ * [XML](book/Appendix-Object-Serialization.md#XML)
-### [附录:静态语言类型检查](book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md)
- * [前言](book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md#前言)
- * [静态类型检查和测试](book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md#静态类型检查和测试)
- * [如何提升打字](book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md#如何提升打字)
- * [生产力的成本](book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md#生产力的成本)
- * [静态和动态](book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md#静态和动态)
+### [附录:对象传递和返回](book/Appendix-Passing-and-Returning-Objects.md)
+ * [传递引用](book/Appendix-Passing-and-Returning-Objects.md#传递引用)
+ * [本地拷贝](book/Appendix-Passing-and-Returning-Objects.md#本地拷贝)
+ * [控制克隆](book/Appendix-Passing-and-Returning-Objects.md#控制克隆)
+ * [不可变类](book/Appendix-Passing-and-Returning-Objects.md#不可变类)
+ * [本章小结](book/Appendix-Passing-and-Returning-Objects.md#本章小结)
+
+### [附录:编程指南](book/Appendix-Programming-Guidelines.md)
+ * [设计](book/Appendix-Programming-Guidelines.md#设计)
+ * [实现](book/Appendix-Programming-Guidelines.md#实现)
+
+### [附录:标准IO](book/Appendix-Standard-IO.md)
+ * [从标准输入中读取](book/Appendix-Standard-IO.md#从标准输入中读取)
+ * [将 System.out 转换成 PrintWriter](book/Appendix-Standard-IO.md#将-Systemout-转换成-PrintWriter)
+ * [重定向标准 I/O](book/Appendix-Standard-IO.md#重定向标准-IO)
+ * [执行控制](book/Appendix-Standard-IO.md#执行控制)
+
+### [附录:补充](book/Appendix-Supplements.md)
+ * [可下载的补充](book/Appendix-Supplements.md#可下载的补充)
+ * [通过Thinking-in-C来巩固Java基础](book/Appendix-Supplements.md#通过Thinking-in-C来巩固Java基础)
+ * [Hand-On Java 电子演示文稿](book/Appendix-Supplements.md#Hand-On-Java-电子演示文稿)
### [附录:C++和Java的优良传统](book/Appendix-The-Positive-Legacy-of-C-plus-plus-and-Java.md)
-### [附录:成为一名程序员](book/Appendix-Becoming-a-Programmer.md)
- * [如何开始](book/Appendix-Becoming-a-Programmer.md#如何开始)
- * [码农生涯](book/Appendix-Becoming-a-Programmer.md#码农生涯)
- * [百分之五的神话](book/Appendix-Becoming-a-Programmer.md#百分之五的神话)
- * [重在动手](book/Appendix-Becoming-a-Programmer.md#重在动手)
- * [像打字般编程](book/Appendix-Becoming-a-Programmer.md#像打字般编程)
- * [做你喜欢的事](book/Appendix-Becoming-a-Programmer.md#做你喜欢的事)
+### [附录:理解equals和hashCode方法](book/Appendix-Understanding-equals-and-hashCode.md)
+ * [equals规范](book/Appendix-Understanding-equals-and-hashCode.md#equals规范)
+ * [哈希和哈希码](book/Appendix-Understanding-equals-and-hashCode.md#哈希和哈希码)
+ * [调优 HashMap](book/Appendix-Understanding-equals-and-hashCode.md#调优-HashMap)
-### [词汇表](book/GLOSSARY.md)
+### [词汇表](book/GLOSSARY.md)
\ No newline at end of file
From 46d067656aa8957780f599e9efa6b3973f4fbabb Mon Sep 17 00:00:00 2001
From: Joe <736777445@qq.com>
Date: Wed, 16 Sep 2020 11:02:52 +0800
Subject: [PATCH 11/68] Update README.md
---
README.md | 4 ----
1 file changed, 4 deletions(-)
diff --git a/README.md b/README.md
index 9d501d37..e6c333a9 100644
--- a/README.md
+++ b/README.md
@@ -115,10 +115,6 @@
如不熟悉 md 排版,可不必纠结,我会在合并 pr 时代为排版
如还有其它问题,欢迎发送 issue,谢谢~
-## 友情链接
-
-[Effective.Java.3rd.Edition 中文版](https://sjsdfg.github.io/effective-java-3rd-chinese/#/)
-
## 开源协议
本项目基于 MIT 协议开源。
From 177735c7c065c08a3cef9037b28b10b73d872d9b Mon Sep 17 00:00:00 2001
From: arobot
Date: Wed, 16 Sep 2020 16:07:31 +0800
Subject: [PATCH 12/68] Update 24-Concurrent-Programming.md (#581)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
原文是”Combining parallel() and limit() is for experts only“,强调这两个方法应该是组合操作,而不是这两个方法是留给专家使用
---
docs/book/24-Concurrent-Programming.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/book/24-Concurrent-Programming.md b/docs/book/24-Concurrent-Programming.md
index 9046c59c..127b6827 100755
--- a/docs/book/24-Concurrent-Programming.md
+++ b/docs/book/24-Concurrent-Programming.md
@@ -747,7 +747,7 @@ public class ParallelStreamPuzzle3 {
现在我们得到多个线程产生不同的值,但它只产生10个请求的值,而不是1024个产生10个值。
-它更快吗?一个更好的问题是:什么时候开始有意义?当然不是这么小的一套;上下文切换的代价远远超过并行性的任何加速。很难想象什么时候用并行生成一个简单的数字序列会有意义。如果你要生成的东西需要很高的成本,它可能有意义 - 但这都是猜测。只有通过测试我们才能知道用并行是否有效。记住这句格言:“首先使它工作,然后使它更快地工作 - 只有当你必须这样做时。”**parallel()**和**limit()**仅供专家使用(把话说在前面,我不认为自己是这里的专家)。
+它更快吗?一个更好的问题是:什么时候开始有意义?当然不是这么小的一套;上下文切换的代价远远超过并行性的任何加速。很难想象什么时候用并行生成一个简单的数字序列会有意义。如果你要生成的东西需要很高的成本,它可能有意义 - 但这都是猜测。只有通过测试我们才能知道用并行是否有效。记住这句格言:“首先使它工作,然后使它更快地工作 - 只有当你必须这样做时。”将**parallel()**和**limit()**结合使用仅供专家操作(把话说在前面,我不认为自己是这里的专家)。
- 并行流只看起来很容易
From 7ff61d1ce86d81eca81cf6ed2ebf0f029494bacd Mon Sep 17 00:00:00 2001
From: arobot
Date: Wed, 16 Sep 2020 17:09:33 +0800
Subject: [PATCH 13/68] Update 24-Concurrent-Programming.md (#582)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
1. 原文”First note there is no SingleThreadExecutor class. newSingleThreadExecutor() is a factory in Executors that
creates that particular kind of ExecutorService. “
2. 顺手修复markdown的一些语法显示。加粗前后尽量跟上空格,不然很多加粗显示异常。
---
docs/book/24-Concurrent-Programming.md | 38 ++++++++++++++------------
1 file changed, 20 insertions(+), 18 deletions(-)
diff --git a/docs/book/24-Concurrent-Programming.md b/docs/book/24-Concurrent-Programming.md
index 127b6827..b8dc1871 100755
--- a/docs/book/24-Concurrent-Programming.md
+++ b/docs/book/24-Concurrent-Programming.md
@@ -396,7 +396,7 @@ Sum Iterated: 284ms
**main()** 的第一个版本使用直接生成 **Stream** 并调用 **sum()** 的方法。我们看到流的好处在于即使SZ为十亿(1_000_000_000)程序也可以很好地处理而没有溢出(为了让程序运行得快一点,我使用了较小的数字)。使用 **parallel()** 的基本范围操作明显更快。
-如果使用**iterate()**来生成序列,则减速是相当明显的,可能是因为每次生成数字时都必须调用lambda。但是如果我们尝试并行化,当**SZ**超过一百万时,结果不仅比非并行版本花费的时间更长,而且也会耗尽内存(在某些机器上)。当然,当你可以使用**range()**时,你不会使用**iterate()**,但如果你生成的东西不是简单的序列,你必须使用**iterate()**。应用**parallel()**是一个合理的尝试,但会产生令人惊讶的结果。我们将在后面的部分中探讨内存限制的原因,但我们可以对流并行算法进行初步观察:
+如果使用**iterate()** 来生成序列,则减速是相当明显的,可能是因为每次生成数字时都必须调用lambda。但是如果我们尝试并行化,当**SZ**超过一百万时,结果不仅比非并行版本花费的时间更长,而且也会耗尽内存(在某些机器上)。当然,当你可以使用**range()**时,你不会使用**iterate()** ,但如果你生成的东西不是简单的序列,你必须使用**iterate()** 。应用**parallel()** 是一个合理的尝试,但会产生令人惊讶的结果。我们将在后面的部分中探讨内存限制的原因,但我们可以对流并行算法进行初步观察:
- 流并行性将输入数据分成多个部分,因此算法可以应用于那些单独的部分。
- 数组分割成本低,分割均匀且对分割的大小有着完美的掌控。
@@ -554,9 +554,9 @@ Long Parallel: 1008ms**
- parallel()/limit()交点
-使用**parallel()**时会有更复杂的问题。从其他语言中吸取的流机制被设计为大约是一个无限的流模型。如果你拥有有限数量的元素,则可以使用集合以及为有限大小的集合设计的关联算法。如果你使用无限流,则使用针对流优化的算法。
+使用 **parallel()** 时会有更复杂的问题。从其他语言中吸取的流机制被设计为大约是一个无限的流模型。如果你拥有有限数量的元素,则可以使用集合以及为有限大小的集合设计的关联算法。如果你使用无限流,则使用针对流优化的算法。
-Java 8将两者合并起来。例如,**Collections**没有内置的**map()**操作。在**Collection**和**Map**中唯一类似流的批处理操作是**forEach()**。如果要执行**map()**和**reduce()**等操作,必须首先将**Collection**转换为存在这些操作的**Stream**:
+Java 8将两者合并起来。例如,**Collections**没有内置的**map()** 操作。在**Collection**和**Map**中唯一类似流的批处理操作是**forEach()** 。如果要执行**map()** 和**reduce()** 等操作,必须首先将**Collection**转换为存在这些操作的**Stream**:
```java
// concurrent/CollectionIntoStream.java
@@ -595,9 +595,9 @@ bynxt
:PENCUXGVGINNLOZVEWPPCPOALJLNXT
```
-**Collection**确实有一些批处理操作,如**removeAll()**,**removeIf()**和**retainAll()**,但这些都是破坏性的操作。**ConcurrentHashMap**对**forEach**和**reduce**操作有特别广泛的支持。
+**Collection**确实有一些批处理操作,如**removeAll()**,**removeIf()** 和**retainAll()** ,但这些都是破坏性的操作。**ConcurrentHashMap**对**forEach**和**reduce**操作有特别广泛的支持。
-在许多情况下,只在集合上调用**stream()**或者**parallelStream()**没有问题。但是,有时将**Stream**与**Collection**混合会产生意想不到的结果。这是一个有趣的难题:
+在许多情况下,只在集合上调用**stream()** 或者**parallelStream()** 没有问题。但是,有时将**Stream**与**Collection**混合会产生意想不到的结果。这是一个有趣的难题:
```java
// concurrent/ParallelStreamPuzzle.java
@@ -672,11 +672,12 @@ public class ParallelStreamPuzzle2 {
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
```
-current是使用线程安全的 **AtomicInteger** 类定义的,可以防止竞争条件;**parallel()**允许多个线程调用**get()**。
+current是使用线程安全的 **AtomicInteger** 类定义的,可以防止竞争条件;**parallel()** 允许多个线程调用**get()**。
-在查看 **PSP2.txt**.**IntGenerator.get()** 被调用1024次时,你可能会感到惊讶。
+在查看 **PSP2.txt** .**IntGenerator.get()** 被调用1024次时,你可能会感到惊讶。
-**0: main
+```
+0: main
1: ForkJoinPool.commonPool-worker-1
2: ForkJoinPool.commonPool-worker-2
3: ForkJoinPool.commonPool-worker-2
@@ -698,7 +699,8 @@ current是使用线程安全的 **AtomicInteger** 类定义的,可以防止竞
20: ForkJoinPool.commonPool-worker-110
21: ForkJoinPool.commonPool-worker-110
22: ForkJoinPool.commonPool-worker-110
-23: ForkJoinPool.commonPool-worker-1**
+23: ForkJoinPool.commonPool-worker-1
+```
这个块大小似乎是内部实现的一部分(尝试使用`limit()` 的不同参数来查看不同的块大小)。将`parallel()`与`limit()`结合使用可以预取一串值,作为流输出。
@@ -741,17 +743,17 @@ public class ParallelStreamPuzzle3 {
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
```
-为了表明**parallel()**确实有效,我添加了一个对**peek()**的调用,这是一个主要用于调试的流函数:它从流中提取一个值并执行某些操作但不影响从流向下传递的元素。注意这会干扰线程行为,但我只是尝试在这里做一些事情,而不是实际调试任何东西。
+为了表明**parallel()**确实有效,我添加了一个对**peek()** 的调用,这是一个主要用于调试的流函数:它从流中提取一个值并执行某些操作但不影响从流向下传递的元素。注意这会干扰线程行为,但我只是尝试在这里做一些事情,而不是实际调试任何东西。
-你还可以看到**boxed()**的添加,它接受**int**流并将其转换为**Integer**流。
+你还可以看到**boxed()** 的添加,它接受**int**流并将其转换为**Integer**流。
现在我们得到多个线程产生不同的值,但它只产生10个请求的值,而不是1024个产生10个值。
-它更快吗?一个更好的问题是:什么时候开始有意义?当然不是这么小的一套;上下文切换的代价远远超过并行性的任何加速。很难想象什么时候用并行生成一个简单的数字序列会有意义。如果你要生成的东西需要很高的成本,它可能有意义 - 但这都是猜测。只有通过测试我们才能知道用并行是否有效。记住这句格言:“首先使它工作,然后使它更快地工作 - 只有当你必须这样做时。”将**parallel()**和**limit()**结合使用仅供专家操作(把话说在前面,我不认为自己是这里的专家)。
+它更快吗?一个更好的问题是:什么时候开始有意义?当然不是这么小的一套;上下文切换的代价远远超过并行性的任何加速。很难想象什么时候用并行生成一个简单的数字序列会有意义。如果你要生成的东西需要很高的成本,它可能有意义 - 但这都是猜测。只有通过测试我们才能知道用并行是否有效。记住这句格言:“首先使它工作,然后使它更快地工作 - 只有当你必须这样做时。”将**parallel()** 和**limit()** 结合使用仅供专家操作(把话说在前面,我不认为自己是这里的专家)。
- 并行流只看起来很容易
-实际上,在许多情况下,并行流确实可以毫不费力地更快地产生结果。但正如你所见,仅仅将**parallel()**加到你的Stream操作上并不一定是安全的事情。在使用**parallel()**之前,你必须了解并行性如何帮助或损害你的操作。一个基本认知错误就是认为使用并行性总是一个好主意。事实上并不是。Stream意味着你不需要重写所有代码便可以并行运行它。但是流的出现并不意味着你可以不用理解并行的原理以及不用考虑并行是否真的有助于实现你的目标。
+实际上,在许多情况下,并行流确实可以毫不费力地更快地产生结果。但正如你所见,仅仅将**parallel()** 加到你的Stream操作上并不一定是安全的事情。在使用**parallel()** 之前,你必须了解并行性如何帮助或损害你的操作。一个基本认知错误就是认为使用并行性总是一个好主意。事实上并不是。Stream意味着你不需要重写所有代码便可以并行运行它。但是流的出现并不意味着你可以不用理解并行的原理以及不用考虑并行是否真的有助于实现你的目标。
## 创建和运行任务
@@ -788,7 +790,7 @@ public class NapTask implements Runnable {
}
```
-这只是一个**Runnable**:一个包含**run()**方法的类。它没有包含实际运行任务的机制。我们使用**Nap**类中的“sleep”:
+这只是一个**Runnable**:一个包含**run()** 方法的类。它没有包含实际运行任务的机制。我们使用**Nap**类中的“sleep”:
```java
// onjava/Nap.java
@@ -810,9 +812,9 @@ public class Nap {
```
为了消除异常处理的视觉干扰,这被定义为实用程序。第二个构造函数在超时时显示一条消息
-对**TimeUnit.MILLISECONDS.sleep()**的调用获取“当前线程”并在参数中将其置于休眠状态,这意味着该线程被挂起。这并不意味着底层处理器停止。操作系统将其切换到其他任务,例如在你的计算机上运行另一个窗口。OS任务管理器定期检查**sleep()**是否超时。当它执行时,线程被“唤醒”并给予更多处理时间。
+对**TimeUnit.MILLISECONDS.sleep()** 的调用获取“当前线程”并在参数中将其置于休眠状态,这意味着该线程被挂起。这并不意味着底层处理器停止。操作系统将其切换到其他任务,例如在你的计算机上运行另一个窗口。OS任务管理器定期检查**sleep()** 是否超时。当它执行时,线程被“唤醒”并给予更多处理时间。
-你可以看到**sleep()**抛出一个受检的**InterruptedException**;这是原始Java设计中的一个工件,它通过突然断开它们来终止任务。因为它往往会产生不稳定的状态,所以后来不鼓励终止。但是,我们必须在需要或仍然发生终止的情况下捕获异常。
+你可以看到**sleep()** 抛出一个受检的**InterruptedException**;这是原始Java设计中的一个工件,它通过突然断开它们来终止任务。因为它往往会产生不稳定的状态,所以后来不鼓励终止。但是,我们必须在需要或仍然发生终止的情况下捕获异常。
要执行任务,我们将从最简单的方法--SingleThreadExecutor开始:
@@ -867,7 +869,7 @@ main awaiting termination
NapTask[9] pool-1-thread-1
```
-首先请注意,没有**SingleThreadExecutor**类。**newSingleThreadExecutor()**是**Executors**中的工厂,它创建特定类型的[^4]
+首先请注意,没有**SingleThreadExecutor**类。**newSingleThreadExecutor()** 是 **Executors** 中的一个工厂方法,它创建特定类型的**ExecutorService**[^4]
我创建了十个NapTasks并将它们提交给ExecutorService,这意味着它们开始自己运行。然而,在此期间,main()继续做事。当我运行callexec.shutdown()时,它告诉ExecutorService完成已经提交的任务,但不接受任何新任务。此时,这些任务仍然在运行,因此我们必须等到它们在退出main()之前完成。这是通过检查exec.isTerminated()来实现的,这在所有任务完成后变为true。
@@ -932,7 +934,7 @@ public class MoreTasksAfterShutdown {
java.util.concurrent.RejectedExecutionException: TaskNapTask[99] rejected from java.util.concurrent.ThreadPoolExecutor@4e25154f[Shutting down, pool size = 1,active threads = 1, queued tasks = 0, completed tasks =0]NapTask[1] pool-1-thread-1
```
-**exec.shutdown()**的替代方法是**exec.shutdownNow()**,它除了不接受新任务外,还会尝试通过中断任务来停止任何当前正在运行的任务。同样,中断是错误的,容易出错并且不鼓励。
+**exec.shutdown()** 的替代方法是**exec.shutdownNow()** ,它除了不接受新任务外,还会尝试通过中断任务来停止任何当前正在运行的任务。同样,中断是错误的,容易出错并且不鼓励。
- 使用更多线程
From 004ebc98aadc607f45f6b444debd7375f050135a Mon Sep 17 00:00:00 2001
From: Joe <736777445@qq.com>
Date: Wed, 16 Sep 2020 17:12:05 +0800
Subject: [PATCH 14/68] Update 24-Concurrent-Programming.md (#583)
---
docs/book/24-Concurrent-Programming.md | 440 ++++++++++++-------------
1 file changed, 220 insertions(+), 220 deletions(-)
diff --git a/docs/book/24-Concurrent-Programming.md b/docs/book/24-Concurrent-Programming.md
index b8dc1871..ab5d177a 100755
--- a/docs/book/24-Concurrent-Programming.md
+++ b/docs/book/24-Concurrent-Programming.md
@@ -3,16 +3,16 @@
# 第二十四章 并发编程
->爱丽丝:“我可不想到疯子中间去”
+> 爱丽丝:“我可不想到疯子中间去”
>
->猫咪:“啊,那没辙了,我们这都是疯子。我疯了,你也疯了”
+> 猫咪:“啊,那没辙了,我们这都是疯子。我疯了,你也疯了”
>
->爱丽丝:“你怎么知道我疯了”。
+> 爱丽丝:“你怎么知道我疯了”。
>
->猫咪:“你一定是疯了,否则你就不会来这儿” ——爱丽丝梦游仙境 第6章。
+> 猫咪:“你一定是疯了,否则你就不会来这儿” ——爱丽丝梦游仙境 第 6 章。
-在本章之前,我们惯用一种简单顺序的叙事方式来编程,有点类似文学中的意识流:第一件事发生了,然后是第二件,第三件……总之,我们完全掌握着事情发生的进展和顺序。如果将值设置为5,再看时它已变成47的话,结果就很匪夷所思了。
+在本章之前,我们惯用一种简单顺序的叙事方式来编程,有点类似文学中的意识流:第一件事发生了,然后是第二件,第三件……总之,我们完全掌握着事情发生的进展和顺序。如果将值设置为 5,再看时它已变成 47 的话,结果就很匪夷所思了。
现在,我们来到了陌生的并发世界。这样的结果一点都不奇怪,因为你原来信赖的一切都不再可靠。它可能有效,也可能无效。更可能得是,它在某些情况下会起作用,而在另一些情况下则不会。只有了解了这些情况,我们才能正确地行事。
@@ -20,11 +20,11 @@
假设我们处在多条故事线并行的间谍小说里,非单一意识流地叙事:第一个间谍在岩石底留下了微缩胶片。当第二个间谍来取时,胶片可能已被第三个间谍拿走。小说并没有交代此处的细节。所以直到故事结尾,我们都没搞清楚到底发生了什么。
-构建并发程序好比玩[搭积木](https://en.wikipedia.org/wiki/Jenga)游戏。每拉出一块放在塔顶时都有崩塌的可能。每个积木塔和应用程序都是独一无二的,有着自己的作用。你在某个系统构建中学到的知识并不一定适用于下一个系统。
+构建并发程序好比玩[搭积木 ](https://en.wikipedia.org/wiki/Jenga) 游戏。每拉出一块放在塔顶时都有崩塌的可能。每个积木塔和应用程序都是独一无二的,有着自己的作用。你在某个系统构建中学到的知识并不一定适用于下一个系统。
本章是对并发概念最基本的介绍。虽然我们用到了现代的 Java 8 工具来演示原理,但还远未及全面论述并发。我的目标是为你提供足够的基础知识,使你能够把握问题的复杂性和危险性,从而安全地渡过这片鲨鱼肆虐的困难水域。
-更多繁琐和底层的细节,请参阅附录:[并发底层原理](./Appendix-Low-Level-Concurrency.md)。要进一步深入这个领域,你还必须阅读 *Brian Goetz* 等人的 《Java Concurrency in Practice》。在撰写本文时,该书已有十多年的历史了,但它仍包含我们必须要了解和明白的知识要点。理想情况下,本章和上述附录是阅读该书的良好前提。另外,*Bill Venner* 的 《Inside the Java Virtual Machine》也很值得一看。它详细描述了 JVM 的内部工作方式,包括线程。
+更多繁琐和底层的细节,请参阅附录:[并发底层原理 ](./Appendix-Low-Level-Concurrency.md)。要进一步深入这个领域,你还必须阅读 *Brian Goetz* 等人的 《Java Concurrency in Practice》。在撰写本文时,该书已有十多年的历史了,但它仍包含我们必须要了解和明白的知识要点。理想情况下,本章和上述附录是阅读该书的良好前提。另外,*Bill Venner* 的 《Inside the Java Virtual Machine》也很值得一看。它详细描述了 JVM 的内部工作方式,包括线程。
@@ -42,7 +42,7 @@
“并发”通常表示:不止一个任务正在执行。而“并行”几乎总是代表:不止一个任务同时执行。现在你能看到问题所在了吗?“并行”也有不止一个任务正在执行的语义在里面。区别就在于细节:究竟是怎么“执行”的。此外,还有一些场景重叠:为并行编写的程序有时在单处理器上运行,而一些并发编程系统可以利用多处理器。
-还有另一种方法,在减速发生的地方写下定义(原文Here’s another approach, writing the definitions around where the
+还有另一种方法,在减速发生的地方写下定义(原文 Here’s another approach, writing the definitions around where the
slowdown occurs):
**并发**
@@ -53,36 +53,36 @@ slowdown occurs):
同时在多个位置完成多任务。这解决了所谓的 CPU 密集型问题:将程序分为多部分,在多个处理器上同时处理不同部分来加快程序执行效率。
-上面的定义说明了这两个术语令人困惑的原因:两者的核心都是“同时完成多个任务”,不过并行增加了跨多个处理器的分布。更重要的是,它们可以解决不同类型的问题:并行可能对解决I / O密集型问题没有任何好处,因为问题不在于程序的整体执行速度,而在于I/O阻塞。而尝试在单个处理器上使用并发来解决计算密集型问题也可能是浪费时间。两种方法都试图在更短的时间内完成更多工作,但是它们实现加速的方式有所不同,这取决于问题施加的约束。
+上面的定义说明了这两个术语令人困惑的原因:两者的核心都是“同时完成多个任务”,不过并行增加了跨多个处理器的分布。更重要的是,它们可以解决不同类型的问题:并行可能对解决 I / O 密集型问题没有任何好处,因为问题不在于程序的整体执行速度,而在于 I/O 阻塞。而尝试在单个处理器上使用并发来解决计算密集型问题也可能是浪费时间。两种方法都试图在更短的时间内完成更多工作,但是它们实现加速的方式有所不同,这取决于问题施加的约束。
-这两个概念混合在一起的一个主要原因是包括Java在内的许多编程语言使用相同的机制 - **线程**来实现并发和并行。
+这两个概念混合在一起的一个主要原因是包括 Java 在内的许多编程语言使用相同的机制 - **线程**来实现并发和并行。
我们甚至可以尝试以更细的粒度去进行定义(然而这并不是标准化的术语):
-- **纯并发**:仍然在单个CPU上运行任务。纯并发系统比顺序系统更快地产生结果,但是它的运行速度不会因为处理器的增加而变得更快。
+- **纯并发**:仍然在单个 CPU 上运行任务。纯并发系统比顺序系统更快地产生结果,但是它的运行速度不会因为处理器的增加而变得更快。
- **并发-并行**:使用并发技术,结果程序可以利用更多处理器更快地产生结果。
-- **并行-并发**:使用并行编程技术编写,如果只有一个处理器,结果程序仍然可以运行(Java 8 **Streams**就是一个很好的例子)。
+- **并行-并发**:使用并行编程技术编写,如果只有一个处理器,结果程序仍然可以运行(Java 8 **Streams** 就是一个很好的例子)。
- **纯并行**:除非有多个处理器,否则不会运行。
在某些情况下,这可能是一个有用的分类法。
-支持并发性的语言和库似乎是[抽象泄露(Leaky Abstraction)](https://en.wikipedia.org/wiki/Leaky_abstraction)一词的完美候选。抽象的目标是“抽象出”那些对于手头想法不重要的东西,以屏蔽不必要的细节。如果抽象是有漏洞的,那些碎片和细节就会不断重新声明自己是重要的,无论你废了多少功夫来隐藏它们。
+支持并发性的语言和库似乎是[抽象泄露(Leaky Abstraction)](https://en.wikipedia.org/wiki/Leaky_abstraction) 一词的完美候选。抽象的目标是“抽象出”那些对于手头想法不重要的东西,以屏蔽不必要的细节。如果抽象是有漏洞的,那些碎片和细节就会不断重新声明自己是重要的,无论你废了多少功夫来隐藏它们。
-我开始怀疑是否真的有高度抽象。因为当编写这类程序时,底层的系统、工具,甚至是关于CPU缓存如何工作的细节,都永远不会被屏蔽。最后,如果你非常小心,你创作的东西在特定的情况下工作,但在其他情况下不工作。有时是两台机器的配置方式不同,有时是程序的估计负载不同。这不是Java特有的 - 这是并发和并行编程的本质。
+我开始怀疑是否真的有高度抽象。因为当编写这类程序时,底层的系统、工具,甚至是关于 CPU 缓存如何工作的细节,都永远不会被屏蔽。最后,如果你非常小心,你创作的东西在特定的情况下工作,但在其他情况下不工作。有时是两台机器的配置方式不同,有时是程序的估计负载不同。这不是 Java 特有的 - 这是并发和并行编程的本质。
-你可能会认为[纯函数式](https://en.wikipedia.org/wiki/Purely_functional)语言没有这些限制。实际上,纯函数式语言解决了大量并发问题,所以如果你正在解决一个困难的并发问题,你可以考虑用纯函数语言编写这个部分。但最终,如果你编写一个使用队列的系统,例如,如果该系统没有被正确地调整,并且输入速率也没有被正确地估计或限制(在不同的情况下,限制意味着具有不同的影响的不同东西),该队列要么被填满并阻塞,要么溢出。最后,你必须了解所有细节,任何问题都可能会破坏你的系统。这是一种非常不同的编程方式。
+你可能会认为[纯函数式 ](https://en.wikipedia.org/wiki/Purely_functional) 语言没有这些限制。实际上,纯函数式语言解决了大量并发问题,所以如果你正在解决一个困难的并发问题,你可以考虑用纯函数语言编写这个部分。但最终,如果你编写一个使用队列的系统,例如,如果该系统没有被正确地调整,并且输入速率也没有被正确地估计或限制(在不同的情况下,限制意味着具有不同的影响的不同东西),该队列要么被填满并阻塞,要么溢出。最后,你必须了解所有细节,任何问题都可能会破坏你的系统。这是一种非常不同的编程方式。
### 并发的新定义
几十年来,我一直在努力解决各种形式的并发问题,其中一个最大的挑战一直是简单地定义它。在撰写本章的过程中,我终于有了这样的洞察力,我认为可以定义它:
->**并发性是一系列性能技术,专注于减少等待**
+>** 并发性是一系列性能技术,专注于减少等待**
这实际上是一个相当复杂的表述,所以我将其分解:
- 这是一个集合:包含许多不同的方法来解决这个问题。这是使定义并发性如此具有挑战性的问题之一,因为技术差异很大。
-- 这些是性能技术:就是这样。并发的关键点在于让你的程序运行得更快。在Java中,并发是非常棘手和困难的,所以绝对不要使用它,除非你有一个重大的性能问题 - 即使这样,使用最简单的方法产生你需要的性能,因为并发很快变得无法管理。
-- “减少等待”部分很重要而且微妙。无论(例如)你运行多少个处理器,你只能在等待发生时产生效益。如果你发起I/O请求并立即获得结果,没有延迟,因此无需改进。如果你在多个处理器上运行多个任务,并且每个处理器都以满容量运行,并且没有任务需要等待其他任务,那么尝试提高吞吐量是没有意义的。并发的唯一机会是如果程序的某些部分被迫等待。等待可以以多种形式出现 - 这解释了为什么存在如此不同的并发方法。
+- 这些是性能技术:就是这样。并发的关键点在于让你的程序运行得更快。在 Java 中,并发是非常棘手和困难的,所以绝对不要使用它,除非你有一个重大的性能问题 - 即使这样,使用最简单的方法产生你需要的性能,因为并发很快变得无法管理。
+- “减少等待”部分很重要而且微妙。无论(例如)你运行多少个处理器,你只能在等待发生时产生效益。如果你发起 I/O 请求并立即获得结果,没有延迟,因此无需改进。如果你在多个处理器上运行多个任务,并且每个处理器都以满容量运行,并且没有任务需要等待其他任务,那么尝试提高吞吐量是没有意义的。并发的唯一机会是如果程序的某些部分被迫等待。等待可以以多种形式出现 - 这解释了为什么存在如此不同的并发方法。
值得强调的是,这个定义的有效性取决于“等待”这个词。如果没有什么可以等待,那就没有机会去加速。如果有什么东西在等待,那么就会有很多方法可以加快速度,这取决于多种因素,包括系统运行的配置,你要解决的问题类型以及其他许多问题。
@@ -95,7 +95,7 @@ slowdown occurs):
现在假设你有一个奇怪的超能力。你可以将自己一分为二,然后在继续前进的同时将另一半送到另一个走廊。每当你在走廊或楼梯上遇到分隔到下一层时,你都会重复这个分裂的技巧。最终,整个建筑中的每个走廊的终点都有一个你。
-每个走廊都有一千个房间。你的超能力变得有点弱,所以你只能分裂出50个自己来搜索这间房间。
+每个走廊都有一千个房间。你的超能力变得有点弱,所以你只能分裂出 50 个自己来搜索这间房间。
一旦克隆体进入房间,它必须搜索房间的每个角落。这时它切换到了第二种超能力。它分裂成了一百万个纳米机器人,每个机器人都会飞到或爬到房间里一些看不见的地方。你不需要了解这种功能 - 一旦你开启它就会自动工作。在他们自己的控制下,纳米机器人开始行动,搜索房间然后回来重新组装成你,突然间,你获得了寻找的物品是否在房间内的消息。
@@ -103,7 +103,7 @@ slowdown occurs):
以下是其中一个漏洞:在理想的世界中,每次克隆自己时,你还会复制硬件处理器来运行该克隆。但当然不会发生这种情况 - 你的机器上可能有四个或八个处理器(通常在写入时)。你可能还有更多,并且仍有许多情况只有一个处理器。在抽象的讨论中,物理处理器的分配方式不仅可以泄漏,甚至可以支配你的决策
-让我们在科幻电影中改变一些东西。现在当每个克隆搜索者最终到达一扇门时,他们必须敲门并等到有人回答。如果我们每个搜索者有一个处理器,这没有问题 - 处理器只是空闲,直到门被回答。但是如果我们只有8个处理器和数千个搜索者,我们不希望处理器仅仅因为某个搜索者恰好在等待回答中被锁住而闲置下来。相反,我们希望将处理器应用于可以真正执行工作的搜索者身上,因此需要将处理器从一个任务切换到另一个任务的机制。
+让我们在科幻电影中改变一些东西。现在当每个克隆搜索者最终到达一扇门时,他们必须敲门并等到有人回答。如果我们每个搜索者有一个处理器,这没有问题 - 处理器只是空闲,直到门被回答。但是如果我们只有 8 个处理器和数千个搜索者,我们不希望处理器仅仅因为某个搜索者恰好在等待回答中被锁住而闲置下来。相反,我们希望将处理器应用于可以真正执行工作的搜索者身上,因此需要将处理器从一个任务切换到另一个任务的机制。
许多模型能够有效地隐藏处理器的数量,并允许你假装你的数量非常大。但是有些情况会发生故障的时候,你必须知道处理器的数量,以便你可以解决这个问题。
@@ -126,7 +126,7 @@ slowdown occurs):
当“同时”执行的任务相互干扰时,会出现问题。它可以以如此微妙和偶然的方式发生,可能公平地说,并发性“可以说是确定性的,但实际上是非确定性的。”也就是说,你可以假设编写通过维护和代码检查正常工作的并发程序。然而,在实践中,我们编写的并发程序似乎都能正常工作,但是在适当的条件下,将会失败。这些情况可能永远不会发生,或者在你在测试期间几乎很难发现它们。实际上,编写测试代码通常无法为并发程序生成故障条件。由此产生的失败只会偶尔发生,因此它们以客户投诉的形式出现。
这是学习并发中最强有力的论点之一:如果你忽略它,你可能会受伤。
-因此,并发似乎充满了危险,如果这让你有点害怕,这可能是一件好事。尽管Java 8在并发性方面做出了很大改进,但仍然没有像编译时验证(compile-time verification)或受检查的异常(checked exceptions)那样的安全网来告诉你何时出现错误。通过并发,你只能依靠自己,只有知识渊博,保持怀疑和积极进取的人,才能用Java编写可靠的并发代码。
+因此,并发似乎充满了危险,如果这让你有点害怕,这可能是一件好事。尽管 Java 8 在并发性方面做出了很大改进,但仍然没有像编译时验证 (compile-time verification) 或受检查的异常 (checked exceptions) 那样的安全网来告诉你何时出现错误。通过并发,你只能依靠自己,只有知识渊博,保持怀疑和积极进取的人,才能用 Java 编写可靠的并发代码。
@@ -136,28 +136,28 @@ slowdown occurs):
速度问题一开始听起来很简单:如果你想要一个程序运行得更快,将其分解成碎片并在一个单独的处理器上运行每个部分。由于我们能够提高时钟速度流(至少对于传统芯片),速度的提高是出现在多核处理器的形式而不是更快的芯片。为了使你的程序运行得更快,你必须学会如何利用那些额外的处理器,这是并发性给你的一个建议。
-使用多处理器机器,可以在这些处理器之间分配多个任务,这可以显着提高吞吐量。强大的多处理器Web服务器通常就是这种情况,它可以在程序中为CPU分配大量用户请求,每个请求分配一个线程。
+使用多处理器机器,可以在这些处理器之间分配多个任务,这可以显着提高吞吐量。强大的多处理器 Web 服务器通常就是这种情况,它可以在程序中为 CPU 分配大量用户请求,每个请求分配一个线程。
但是,并发性通常可以提高在单个处理器上运行的程序的性能。这听起来有点违反直觉。如果考虑一下,由于上下文切换的成本增加(从一个任务更改为另一个任务),在单个处理器上运行的并发程序实际上应该比程序的所有部分顺序运行具有更多的开销。在表面上,将程序的所有部分作为单个任务运行并节省上下文切换的成本似乎更便宜。
-可以产生影响的问题是阻塞。如果你的程序中的一个任务由于程序控制之外的某些条件(通常是I/O)而无法继续,我们会说任务或线程阻塞(在我们的科幻故事中,克隆体已敲门而且是等待它打开)。如果没有并发性,整个程序就会停止,直到外部条件发生变化。但是,如果使用并发编写程序,则当一个任务被阻止时,程序中的其他任务可以继续执行,因此程序继续向前移动。实际上,从性能的角度来看,在单处理器机器上使用并发是没有意义的,除非其中一个任务可能阻塞。
+可以产生影响的问题是阻塞。如果你的程序中的一个任务由于程序控制之外的某些条件(通常是 I/O)而无法继续,我们会说任务或线程阻塞(在我们的科幻故事中,克隆体已敲门而且是等待它打开)。如果没有并发性,整个程序就会停止,直到外部条件发生变化。但是,如果使用并发编写程序,则当一个任务被阻止时,程序中的其他任务可以继续执行,因此程序继续向前移动。实际上,从性能的角度来看,在单处理器机器上使用并发是没有意义的,除非其中一个任务可能阻塞。
单处理器系统中性能改进的一个常见例子是事件驱动编程,特别是用户界面编程。考虑一个程序执行一些长时间运行操作,从而最终忽略用户输入和无响应。如果你有一个“退出”按钮,你不想在你编写的每段代码中轮询它。这会产生笨拙的代码,无法保证程序员不会忘记执行检查。没有并发性,生成响应式用户界面的唯一方法是让所有任务定期检查用户输入。通过创建单独的执行线程来响应用户输入,该程序保证了一定程度的响应。
-实现并发的直接方法是在操作系统级别,使用与线程不同的进程。进程是一个在自己的地址空间内运行的自包含程序。进程很有吸引力,因为操作系统通常将一个进程与另一个进程隔离,因此它们不会相互干扰,这使得进程编程相对容易。相比之下,线程共享内存和I/O等资源,因此编写多线程程序时遇到的困难是在不同的线程驱动的任务之间协调这些资源,一次不能通过多个任务访问它们。
+实现并发的直接方法是在操作系统级别,使用与线程不同的进程。进程是一个在自己的地址空间内运行的自包含程序。进程很有吸引力,因为操作系统通常将一个进程与另一个进程隔离,因此它们不会相互干扰,这使得进程编程相对容易。相比之下,线程共享内存和 I/O 等资源,因此编写多线程程序时遇到的困难是在不同的线程驱动的任务之间协调这些资源,一次不能通过多个任务访问它们。
有些人甚至提倡将进程作为并发的唯一合理方法[^1],但不幸的是,通常存在数量和开销限制,从而阻止了在并发范围内的适用性(最终你会习惯标准的并发限制,“这种方法适用于一些情况但不适用于其他情况”)
-一些编程语言旨在将并发任务彼此隔离。这些通常被称为_函数式语言_,其中每个函数调用不产生其他影响(因此不能与其他函数干涉),因此可以作为独立的任务来驱动。Erlang就是这样一种语言,它包括一个任务与另一个任务进行通信的安全机制。如果你发现程序的某一部分必须大量使用并发性并且你在尝试构建该部分时遇到了过多的问题,那么你可能会考虑使用专用并发语言创建程序的那一部分。
+一些编程语言旨在将并发任务彼此隔离。这些通常被称为_函数式语言_,其中每个函数调用不产生其他影响(因此不能与其他函数干涉),因此可以作为独立的任务来驱动。Erlang 就是这样一种语言,它包括一个任务与另一个任务进行通信的安全机制。如果你发现程序的某一部分必须大量使用并发性并且你在尝试构建该部分时遇到了过多的问题,那么你可能会考虑使用专用并发语言创建程序的那一部分。
-Java采用了更传统的方法[^2],即在顺序语言之上添加对线程的支持而不是在多任务操作系统中分配外部进程,线程在执行程序所代表的单个进程中创建任务交换。
+Java 采用了更传统的方法[^2],即在顺序语言之上添加对线程的支持而不是在多任务操作系统中分配外部进程,线程在执行程序所代表的单个进程中创建任务交换。
并发性会带来成本,包括复杂性成本,但可以通过程序设计,资源平衡和用户便利性的改进来抵消。通常,并发性使你能够创建更加松散耦合的设计;除此以外,你必须特别关注那些使用了并发操作的代码。
## 四句格言
-在经历了多年的Java并发之后,我总结了以下四个格言:
+在经历了多年的 Java 并发之后,我总结了以下四个格言:
>1.不要这样做
>
>2.没有什么是真的,一切可能都有问题
@@ -166,7 +166,7 @@ Java采用了更传统的方法[^2],即在顺序语言之上添加对线程的
>
>4.你仍然必须理解它
-这些格言专门针对Java的并发设计问题,尽管它们也可以适用于其他一些语言。但是,确实存在旨在防止这些问题的语言。
+这些格言专门针对 Java 的并发设计问题,尽管它们也可以适用于其他一些语言。但是,确实存在旨在防止这些问题的语言。
### 1.不要这样做
@@ -186,7 +186,7 @@ Java采用了更传统的方法[^2],即在顺序语言之上添加对线程的
在非并发程序中你可以忽略的各种事情在并发程序中突然变得非常重要。例如,你必须知道处理器缓存以及保持本地缓存与主内存一致的问题。你必须深入了解对象构造的复杂性,以便你的构造器不会意外地将数据暴露给其他线程进行更改。问题还有很多。
-因为这些主题太复杂,本章无法为你提供更专业的知识(再次参见Java Concurrency in Practice),但你必须了解它们。
+因为这些主题太复杂,本章无法为你提供更专业的知识(再次参见 Java Concurrency in Practice),但你必须了解它们。
### 3.它起作用,并不意味着它没有问题
@@ -197,28 +197,28 @@ Java采用了更传统的方法[^2],即在顺序语言之上添加对线程的
- 你通常不能编写有用的测试,因此你必须依靠代码检查结合深入的并发知识来发现错误。
- 即使是有效的程序也只能在其设计参数下工作。当超出这些设计参数时,大多数并发程序会以某种方式失败。
-在其他 Java 主题中,我们培养了一种感觉-决定论。一切都按照语言的承诺(或隐含)进行,这是令人欣慰和期待的 - 毕竟,编程语言的目的是让机器做我们想要的。从确定性编程的世界进入并发编程领域,我们遇到了一种称为[Dunning-Kruger](https://en.wikipedia.org/wiki/Dunning%E2%80%93Kruger_effect)效应的认知偏差,可以概括为“无知者无畏。”这意味着“......相对不熟练的人拥有着虚幻的优越感,错误地评估他们的能力远高于实际。
+在其他 Java 主题中,我们培养了一种感觉-决定论。一切都按照语言的承诺(或隐含)进行,这是令人欣慰和期待的 - 毕竟,编程语言的目的是让机器做我们想要的。从确定性编程的世界进入并发编程领域,我们遇到了一种称为[Dunning-Kruger](https://en.wikipedia.org/wiki/Dunning%E2%80%93Kruger_effect) 效应的认知偏差,可以概括为“无知者无畏。”这意味着“......相对不熟练的人拥有着虚幻的优越感,错误地评估他们的能力远高于实际。
我自己的经验是,无论你是多么确定你的代码是线程安全的,它可能已经无效了。你可以很容易地了解所有的问题,然后几个月或几年后你会发现一些概念让你意识到你编写的大多数内容实际上都容易受到并发错误的影响。当某些内容不正确时,编译器不会告诉你。为了使它正确,你必须在研究代码前了解所有并发问题。
-在Java的所有非并发领域,“没有明显的错误和没有明显的编译错误”似乎意味着一切都好。对于并发,它没有任何意义。在这种情况你最糟糕的表现就是“自信”。
+在 Java 的所有非并发领域,“没有明显的错误和没有明显的编译错误”似乎意味着一切都好。对于并发,它没有任何意义。在这种情况你最糟糕的表现就是“自信”。
### 4.你必须仍然理解
-在格言1-3之后,你可能会对并发性感到害怕,并且认为,“到目前为止,我已经避免了它,也许我可以继续避免它。
+在格言 1-3 之后,你可能会对并发性感到害怕,并且认为,“到目前为止,我已经避免了它,也许我可以继续避免它。
-这是一种理性的反应。你可能知道其他编程语言更好地设计用于构建并发程序 - 甚至是在JVM上运行的程序(从而提供与Java的轻松通信),例如Clojure或Scala。为什么不用这些语言编写并发部分并将Java用于其他所有部分呢?
+这是一种理性的反应。你可能知道其他编程语言更好地设计用于构建并发程序 - 甚至是在 JVM 上运行的程序(从而提供与 Java 的轻松通信),例如 Clojure 或 Scala。为什么不用这些语言编写并发部分并将 Java 用于其他所有部分呢?
唉,你不能轻易逃脱:
-- 即使你从未明确地创建一个线程,你可能使用的框架 - 例如,Swing图形用户界面(GUI)库,或者像**Timer** class那样简单的东西。
+- 即使你从未明确地创建一个线程,你可能使用的框架 - 例如,Swing 图形用户界面(GUI)库,或者像 **Timer** class 那样简单的东西。
- 这是最糟糕的事情:当你创建组件时,你必须假设这些组件可能在多线程环境中重用。即使你的解决方案是放弃并声明你的组件“不是线程安全的”,你仍然必须知道这样的声明是重要的,它是什么意思?
人们有时会认为并发性太难,不能包含在介绍该语言的书中。他们认为并发是一个可以独立对待的独立主题,并且它在日常编程中出现的少数情况(例如图形用户界面)可以用特殊的习语来处理。如果你可以避免它,为什么要介绍这样的复杂的主题。
-唉,如果只是这样的话,那就太好了。但不幸的是,你无法选择何时在Java程序中出现线程。仅仅你从未写过自己的线程,并不意味着你可以避免编写线程代码。例如,Web系统是最常见的Java应用程序之一,本质上是多线程的Web服务器通常包含多个处理器,而并行性是利用这些处理器的理想方式。就像这样的系统看起来那么简单,你必须理解并发才能正确地编写它。
+唉,如果只是这样的话,那就太好了。但不幸的是,你无法选择何时在 Java 程序中出现线程。仅仅你从未写过自己的线程,并不意味着你可以避免编写线程代码。例如,Web 系统是最常见的 Java 应用程序之一,本质上是多线程的 Web 服务器通常包含多个处理器,而并行性是利用这些处理器的理想方式。就像这样的系统看起来那么简单,你必须理解并发才能正确地编写它。
-Java是一种多线程语言,不管你有没有意识到并发问题,它就在那里。因此,有许多Java程序正在使用中,或者只是偶然工作,或者大部分时间工作并且不时地发生问题,因为。有时这种问题是相对良性的,但有时它意味着丢失有价值的数据,如果你没有意识到并发问题,你最终可能会把问题放在其他地方而不是你的代码中。如果将程序移动到多处理器系统,则可以暴露或放大这些类型的问题。基本上,了解并发性使你意识到正确的程序可能会表现出错误的行为。
+Java 是一种多线程语言,不管你有没有意识到并发问题,它就在那里。因此,有许多 Java 程序正在使用中,或者只是偶然工作,或者大部分时间工作并且不时地发生问题,因为。有时这种问题是相对良性的,但有时它意味着丢失有价值的数据,如果你没有意识到并发问题,你最终可能会把问题放在其他地方而不是你的代码中。如果将程序移动到多处理器系统,则可以暴露或放大这些类型的问题。基本上,了解并发性使你意识到正确的程序可能会表现出错误的行为。
## 残酷的真相
@@ -229,51 +229,51 @@ Java是一种多线程语言,不管你有没有意识到并发问题,它就
有了这种根本性的人类变化,看到许多破坏和失败的实验并不令人惊讶。实际上,进化依赖于无数的实验,其中大多数都失败了。这些实验是向前发展的必要条件。
-Java是在充满自信,热情和睿智的氛围中创建的。在发明一种编程语言时,很容易感觉语言的初始可塑性会持续存在一样,你可以把某些东西拿出来,如果不能解决问题,那么就修复它。编程语言以这种方式是独一无二的 - 它们经历了类似水的改变:气态,液态和最终的固态。在气态阶段,灵活性似乎是无限的,并且很容易认为它总是那样。一旦人们开始使用你的语言,变化就会变得更加严重,环境变得更加粘稠。语言设计的过程本身就是一门艺术。
+Java 是在充满自信,热情和睿智的氛围中创建的。在发明一种编程语言时,很容易感觉语言的初始可塑性会持续存在一样,你可以把某些东西拿出来,如果不能解决问题,那么就修复它。编程语言以这种方式是独一无二的 - 它们经历了类似水的改变:气态,液态和最终的固态。在气态阶段,灵活性似乎是无限的,并且很容易认为它总是那样。一旦人们开始使用你的语言,变化就会变得更加严重,环境变得更加粘稠。语言设计的过程本身就是一门艺术。
-紧迫感来自互联网的最初兴起。它似乎是一场比赛,第一个通过起跑线的人将“获胜”(事实上,Java,JavaScript和PHP等语言的流行程度可以证明这一点)。唉,通过匆忙设计语言而产生的认知负荷和技术债务最终会赶上我们。
+紧迫感来自互联网的最初兴起。它似乎是一场比赛,第一个通过起跑线的人将“获胜”(事实上,Java,JavaScript 和 PHP 等语言的流行程度可以证明这一点)。唉,通过匆忙设计语言而产生的认知负荷和技术债务最终会赶上我们。
-[Turing completeness](https://en.wikipedia.org/wiki/Turing_completeness)是不足够的;语言需要更多的东西:它们必须能够创造性地表达,而不是用不必要的东西来衡量我们。解放我们的心理能力只是为了扭转并再次陷入困境,这是毫无意义的。我承认,尽管存在这些问题,我们已经完成了令人惊奇的事情,但我也知道如果没有这些问题我们能做得更多。
+[Turing completeness](https://en.wikipedia.org/wiki/Turing_completeness) 是不足够的;语言需要更多的东西:它们必须能够创造性地表达,而不是用不必要的东西来衡量我们。解放我们的心理能力只是为了扭转并再次陷入困境,这是毫无意义的。我承认,尽管存在这些问题,我们已经完成了令人惊奇的事情,但我也知道如果没有这些问题我们能做得更多。
-热情使原始Java设计师加入了一些似乎有必要的特性。信心(以及气态的初始语言)让他们认为任何问题随后都可以解决。在时间轴的某个地方,有人认为任何加入Java的东西是固定的和永久性的 -他们非常有信心,并相信第一个决定永远是正确的,因此我们看到Java的体系中充斥着糟糕的决策。其中一些决定最终没有什么后果;例如,你可以告诉人们不要使用Vector,但只能在语言中继续保留它以便对之前版本的支持。
+热情使原始 Java 设计师加入了一些似乎有必要的特性。信心(以及气态的初始语言)让他们认为任何问题随后都可以解决。在时间轴的某个地方,有人认为任何加入 Java 的东西是固定的和永久性的 -他们非常有信心,并相信第一个决定永远是正确的,因此我们看到 Java 的体系中充斥着糟糕的决策。其中一些决定最终没有什么后果;例如,你可以告诉人们不要使用 Vector,但只能在语言中继续保留它以便对之前版本的支持。
-线程包含在Java 1.0中。当然,对java来说支持并发是一个很基本的设计决定,该特性影响了这个语言的各个角落,我们很难想象以后在以后的版本添加它。公平地说,当时并不清楚基本的并发性是多少。像C这样的其他语言能够将线程视为一个附加功能,因此Java设计师也纷纷效仿,包括一个Thread类和必要的JVM支持(这比你想象的要复杂得多)。
+线程包含在 Java 1.0 中。当然,对 java 来说支持并发是一个很基本的设计决定,该特性影响了这个语言的各个角落,我们很难想象以后在以后的版本添加它。公平地说,当时并不清楚基本的并发性是多少。像 C 这样的其他语言能够将线程视为一个附加功能,因此 Java 设计师也纷纷效仿,包括一个 Thread 类和必要的 JVM 支持(这比你想象的要复杂得多)。
-C语言是面向过程语言,这限制了它的野心。这些限制使附加线程库合理。当采用原始模型并将其粘贴到复杂语言中时,Java的大规模扩展迅速暴露了基本问题。在Thread类中的许多方法的弃用以及后续的高级库浪潮中,这种情况变得明显,这些库试图提供更好的并发抽象。
+C 语言是面向过程语言,这限制了它的野心。这些限制使附加线程库合理。当采用原始模型并将其粘贴到复杂语言中时,Java 的大规模扩展迅速暴露了基本问题。在 Thread 类中的许多方法的弃用以及后续的高级库浪潮中,这种情况变得明显,这些库试图提供更好的并发抽象。
-不幸的是,为了在更高级别的语言中获得并发性,所有语言功能都会受到影响,包括最基本的功能,例如标识符代表可变值。在简化并发编程中,所有函数和方法中为了保持事物不变和防止副作用都要做出巨大的改变(这些是纯函数式编程语言的基础),但当时对于主流语言的创建者来说似乎是奇怪的想法。最初的Java设计师要么没有意识到这些选择,要么认为它们太不同了,并且会劝退许多潜在的语言使用者。我们可以慷慨地说,语言设计社区当时根本没有足够的经验来理解调整在线程库中的影响。
+不幸的是,为了在更高级别的语言中获得并发性,所有语言功能都会受到影响,包括最基本的功能,例如标识符代表可变值。在简化并发编程中,所有函数和方法中为了保持事物不变和防止副作用都要做出巨大的改变(这些是纯函数式编程语言的基础),但当时对于主流语言的创建者来说似乎是奇怪的想法。最初的 Java 设计师要么没有意识到这些选择,要么认为它们太不同了,并且会劝退许多潜在的语言使用者。我们可以慷慨地说,语言设计社区当时根本没有足够的经验来理解调整在线程库中的影响。
-Java实验告诉我们,结果是悄然灾难性的。程序员很容易陷入认为Java 线程并不那么困难的陷阱。表面上看起来正常工作的程序实际上充满了微妙的并发bug。
+Java 实验告诉我们,结果是悄然灾难性的。程序员很容易陷入认为 Java 线程并不那么困难的陷阱。表面上看起来正常工作的程序实际上充满了微妙的并发 bug。
为了获得正确的并发性,语言功能必须从头开始设计并考虑并发性。木已成舟;Java 将不再是为并发而设计的语言,而只是一种允许并发的语言。
-尽管有这些基本的不可修复的缺陷,但令人印象深刻的是它已经走了这么远。Java的后续版本添加了库,以便在使用并发时提升抽象级别。事实上,我根本不会想到有可能在Java 8中进行改进:并行流和**CompletableFutures** - 这是惊人的史诗般的变化,我会惊奇地重复的查看它[^3]。
+尽管有这些基本的不可修复的缺陷,但令人印象深刻的是它已经走了这么远。Java 的后续版本添加了库,以便在使用并发时提升抽象级别。事实上,我根本不会想到有可能在 Java 8 中进行改进:并行流和 **CompletableFutures** - 这是惊人的史诗般的变化,我会惊奇地重复的查看它[^3]。
-这些改进非常有用,我们将在本章重点介绍并行流和**CompletableFutures**。虽然它们可以大大简化你对并发和后续代码的思考方式,但基本问题仍然存在:由于Java的原始设计,代码的所有部分仍然很脆弱,你仍然必须理解这些复杂和微妙的问题。Java中的线程绝不是简单或安全的;那种经历必须降级为另一种更新的语言。
+这些改进非常有用,我们将在本章重点介绍并行流和 **CompletableFutures** 。虽然它们可以大大简化你对并发和后续代码的思考方式,但基本问题仍然存在:由于 Java 的原始设计,代码的所有部分仍然很脆弱,你仍然必须理解这些复杂和微妙的问题。Java 中的线程绝不是简单或安全的;那种经历必须降级为另一种更新的语言。
## 本章其余部分
-这是我们将在本章的其余部分介绍的内容。请记住,本章的重点是使用最新的高级Java并发结构。相比于旧的替代品,使用这些会使你的生活更加轻松。但是,你仍会在遗留代码中遇到一些低级工具。有时,你可能会被迫自己使用其中的一些。附录:[并发底层原理](./Appendix-Low-Level-Concurrency.md)包含一些更原始的Java并发元素的介绍。
+这是我们将在本章的其余部分介绍的内容。请记住,本章的重点是使用最新的高级 Java 并发结构。相比于旧的替代品,使用这些会使你的生活更加轻松。但是,你仍会在遗留代码中遇到一些低级工具。有时,你可能会被迫自己使用其中的一些。附录:[并发底层原理 ](./Appendix-Low-Level-Concurrency.md) 包含一些更原始的 Java 并发元素的介绍。
- Parallel Streams(并行流)
-到目前为止,我已经强调了Java 8 Streams提供的改进语法。现在该语法(作为一个粉丝,我希望)会使你感到舒适,你可以获得额外的好处:你可以通过简单地将parallel()添加到表达式来并行化流。这是一种简单,强大,坦率地说是利用多处理器的惊人方式
+到目前为止,我已经强调了 Java 8 Streams 提供的改进语法。现在该语法(作为一个粉丝,我希望)会使你感到舒适,你可以获得额外的好处:你可以通过简单地将 parallel() 添加到表达式来并行化流。这是一种简单,强大,坦率地说是利用多处理器的惊人方式
-添加parallel()来提高速度似乎是微不足道的,但是,唉,它就像你刚刚在[残酷的真相](#The-Brutal-Truth)中学到的那样简单。我将演示并解释一些盲目添加parallel()到Stream表达式的缺陷。
+添加 parallel() 来提高速度似乎是微不足道的,但是,唉,它就像你刚刚在[残酷的真相 ](#The-Brutal-Truth) 中学到的那样简单。我将演示并解释一些盲目添加 parallel() 到 Stream 表达式的缺陷。
- 创建和运行任务
-任务是一段可以独立运行的代码。为了解释创建和运行任务的一些基础知识,本节介绍了一种比并行流或CompletableFutures更简单的机制:Executor。执行者管理一些低级Thread对象(Java中最原始的并发形式)。你创建一个任务,然后将其交给Executor去运行。
+任务是一段可以独立运行的代码。为了解释创建和运行任务的一些基础知识,本节介绍了一种比并行流或 CompletableFutures 更简单的机制:Executor。执行者管理一些低级 Thread 对象(Java 中最原始的并发形式)。你创建一个任务,然后将其交给 Executor 去运行。
-有多种类型的Executor用于不同的目的。在这里,我们将展示规范形式,代表创建和运行任务的最简单和最佳方法。
+有多种类型的 Executor 用于不同的目的。在这里,我们将展示规范形式,代表创建和运行任务的最简单和最佳方法。
- 终止长时间运行的任务
-任务独立运行,因此需要一种机制来关闭它们。典型的方法使用了一个标志,这引入了共享内存的问题,我们将使用Java的“Atomic”库来回避它。
+任务独立运行,因此需要一种机制来关闭它们。典型的方法使用了一个标志,这引入了共享内存的问题,我们将使用 Java 的“Atomic”库来回避它。
- Completable Futures
-当你将衣服带到干洗店时,他们会给你一张收据。你继续完成其他任务,当你的衣服洗干净时你可以把它取走。收据是你与干洗店在后台执行的任务的连接。这是Java 5中引入的Future的方法。
+当你将衣服带到干洗店时,他们会给你一张收据。你继续完成其他任务,当你的衣服洗干净时你可以把它取走。收据是你与干洗店在后台执行的任务的连接。这是 Java 5 中引入的 Future 的方法。
-Future比以前的方法更方便,但你仍然必须出现并用收据取出干洗,如果任务没有完成你还需要等待。对于一系列操作,Futures并没有真正帮助那么多。
+Future 比以前的方法更方便,但你仍然必须出现并用收据取出干洗,如果任务没有完成你还需要等待。对于一系列操作,Futures 并没有真正帮助那么多。
-Java 8 CompletableFuture是一个更好的解决方案:它允许你将操作链接在一起,因此你不必将代码写入接口排序操作。有了CompletableFuture完美的结合,就可以更容易地做出“采购原料,组合成分,烹饪食物,提供食物,收拾餐具,储存餐具”等一系列链式操作。
+Java 8 CompletableFuture 是一个更好的解决方案:它允许你将操作链接在一起,因此你不必将代码写入接口排序操作。有了 CompletableFuture 完美的结合,就可以更容易地做出“采购原料,组合成分,烹饪食物,提供食物,收拾餐具,储存餐具”等一系列链式操作。
- 死锁
某些任务必须去**等待 - 阻塞**来获得其他任务的结果。被阻止的任务有可能等待另一个被阻止的任务,另一个被阻止的任务也在等待其他任务,等等。如果被阻止的任务链循环到第一个,没有人可以取得任何进展,你就会陷入死锁。
@@ -284,14 +284,14 @@ Java 8 CompletableFuture是一个更好的解决方案:它允许你将操作
* 努力,复杂,成本
-我们将通过模拟创建披萨的过程完成本章,首先使用并行流实现它,然后是CompletableFutures。这不仅仅是两种方法的比较,更重要的是探索你应该投入多少工作来使你的程序变得更快。
+我们将通过模拟创建披萨的过程完成本章,首先使用并行流实现它,然后是 CompletableFutures。这不仅仅是两种方法的比较,更重要的是探索你应该投入多少工作来使你的程序变得更快。
## 并行流
-Java 8流的一个显著优点是,在某些情况下,它们可以很容易地并行化。这来自仔细的库设计,特别是流使用内部迭代的方式 - 也就是说,它们控制着自己的迭代器。特别是,他们使用一种特殊的迭代器,称为Spliterator,它被限制为易于自动分割。我们只需要念 `.parallel()` 就会产生魔法般的结果,流中的所有内容都作为一组并行任务运行。如果你的代码是使用Streams编写的,那么并行化以提高速度似乎是一种琐事
+Java 8 流的一个显著优点是,在某些情况下,它们可以很容易地并行化。这来自仔细的库设计,特别是流使用内部迭代的方式 - 也就是说,它们控制着自己的迭代器。特别是,他们使用一种特殊的迭代器,称为 Spliterator,它被限制为易于自动分割。我们只需要念 `.parallel()` 就会产生魔法般的结果,流中的所有内容都作为一组并行任务运行。如果你的代码是使用 Streams 编写的,那么并行化以提高速度似乎是一种琐事
-例如,考虑来自Streams的Prime.java。查找质数可能是一个耗时的过程,我们可以看到该程序的计时:
+例如,考虑来自 Streams 的 Prime.java。查找质数可能是一个耗时的过程,我们可以看到该程序的计时:
```java
// concurrent/ParallelPrime.java
@@ -330,19 +330,19 @@ public class ParallelPrime {
1224
```
-请注意,这不是微基准测试,因为我们计时整个程序。我们将数据保存在磁盘上以防止编译器过激的优化;如果我们没有对结果做任何事情,那么一个高级的编译器可能会观察到程序没有意义并且终止了计算(这不太可能,但并非不可能)。请注意使用nio2库编写文件的简单性(在[文件](./17-Files.md)一章中有描述)。
+请注意,这不是微基准测试,因为我们计时整个程序。我们将数据保存在磁盘上以防止编译器过激的优化;如果我们没有对结果做任何事情,那么一个高级的编译器可能会观察到程序没有意义并且终止了计算(这不太可能,但并非不可能)。请注意使用 nio2 库编写文件的简单性(在[文件 ](./17-Files.md) 一章中有描述)。
-当我注释掉[1] parallel()行时,我的结果用时大约是parallel()的三倍。
+当我注释掉[1] parallel() 行时,我的结果用时大约是 parallel() 的三倍。
-并行流似乎是一个甜蜜的交易。你所需要做的就是将编程问题转换为流,然后插入parallel()以加快速度。实际上,有时候这很容易。但遗憾的是,有许多陷阱。
+并行流似乎是一个甜蜜的交易。你所需要做的就是将编程问题转换为流,然后插入 parallel() 以加快速度。实际上,有时候这很容易。但遗憾的是,有许多陷阱。
-- parallel()不是灵丹妙药
+- parallel() 不是灵丹妙药
-作为对流和并行流的不确定性的探索,让我们看一个看似简单的问题:对增长的数字序列进行求和。事实证明有大量的方式去实现它,并且我将冒险用计时器将它们进行比较 - 我会尽量小心,但我承认我可能会在计时代码执行时遇到许多基本陷阱之一。结果可能有一些缺陷(例如JVM没有“热身”),但我认为它仍然提供了一些有用的指示。
+作为对流和并行流的不确定性的探索,让我们看一个看似简单的问题:对增长的数字序列进行求和。事实证明有大量的方式去实现它,并且我将冒险用计时器将它们进行比较 - 我会尽量小心,但我承认我可能会在计时代码执行时遇到许多基本陷阱之一。结果可能有一些缺陷(例如 JVM 没有“热身”),但我认为它仍然提供了一些有用的指示。
-我将从一个计时方法**timeTest()**开始,它采用**LongSupplier**,测量**getAsLong()**调用的长度,将结果与**checkValue**进行比较并显示结果。
+我将从一个计时方法 **timeTest()** 开始,它采用 **LongSupplier** ,测量 **getAsLong()** 调用的长度,将结果与 **checkValue** 进行比较并显示结果。
-请注意,一切都必须严格使用**long**;我花了一些时间发现隐蔽的溢出,然后才意识到在重要的地方错过了**long**。
+请注意,一切都必须严格使用 **long** ;我花了一些时间发现隐蔽的溢出,然后才意识到在重要的地方错过了 **long** 。
所有关于时间和内存的数字和讨论都是指“我的机器”。你的经历可能会有所不同。
@@ -392,21 +392,21 @@ Sum Stream Parallel: 46ms
Sum Iterated: 284ms
```
-**CHECK**值是使用Carl Friedrich Gauss(高斯)在1700年代后期还在上小学的时候创建的公式计算出来的.
+**CHECK** 值是使用 Carl Friedrich Gauss(高斯)在 1700 年代后期还在上小学的时候创建的公式计算出来的.
- **main()** 的第一个版本使用直接生成 **Stream** 并调用 **sum()** 的方法。我们看到流的好处在于即使SZ为十亿(1_000_000_000)程序也可以很好地处理而没有溢出(为了让程序运行得快一点,我使用了较小的数字)。使用 **parallel()** 的基本范围操作明显更快。
+ **main()** 的第一个版本使用直接生成 **Stream** 并调用 **sum()** 的方法。我们看到流的好处在于即使 SZ 为十亿(1_000_000_000)程序也可以很好地处理而没有溢出(为了让程序运行得快一点,我使用了较小的数字)。使用 **parallel()** 的基本范围操作明显更快。
-如果使用**iterate()** 来生成序列,则减速是相当明显的,可能是因为每次生成数字时都必须调用lambda。但是如果我们尝试并行化,当**SZ**超过一百万时,结果不仅比非并行版本花费的时间更长,而且也会耗尽内存(在某些机器上)。当然,当你可以使用**range()**时,你不会使用**iterate()** ,但如果你生成的东西不是简单的序列,你必须使用**iterate()** 。应用**parallel()** 是一个合理的尝试,但会产生令人惊讶的结果。我们将在后面的部分中探讨内存限制的原因,但我们可以对流并行算法进行初步观察:
+如果使用 **iterate()** 来生成序列,则减速是相当明显的,可能是因为每次生成数字时都必须调用 lambda。但是如果我们尝试并行化,当 **SZ** 超过一百万时,结果不仅比非并行版本花费的时间更长,而且也会耗尽内存(在某些机器上)。当然,当你可以使用 **range()** 时,你不会使用 **iterate()** ,但如果你生成的东西不是简单的序列,你必须使用 **iterate()** 。应用 **parallel()** 是一个合理的尝试,但会产生令人惊讶的结果。我们将在后面的部分中探讨内存限制的原因,但我们可以对流并行算法进行初步观察:
- 流并行性将输入数据分成多个部分,因此算法可以应用于那些单独的部分。
- 数组分割成本低,分割均匀且对分割的大小有着完美的掌控。
- 链表没有这些属性;“拆分”一个链表仅仅意味着把它分成“第一元素”和“其余元素”,这相对无用。
-- 无状态生成器的行为类似于数组;上面使用的 **range()** 就是无状态的。
-- 迭代生成器的行为类似于链表; **iterate()** 是一个迭代生成器。
+- 无状态生成器的行为类似于数组;上面使用的 **range()** 就是无状态的。
+- 迭代生成器的行为类似于链表; **iterate()** 是一个迭代生成器。
现在让我们尝试通过在数组中填充值并对数组求和来解决问题。因为数组只分配了一次,所以我们不太可能遇到垃圾收集时序问题。
-首先我们将尝试一个充满原始**long**的数组:
+首先我们将尝试一个充满原始 **long** 的数组:
```java
// concurrent/Summing2.java
@@ -451,9 +451,9 @@ Basic Sum: 106ms
parallelPrefix: 265ms
```
-第一个限制是内存大小;因为数组是预先分配的,所以我们不能创建几乎与以前版本一样大的任何东西。并行化可以加快速度,甚至比使用 **basicSum()** 循环更快。有趣的是, **Arrays.parallelPrefix()** 似乎实际上减慢了速度。但是,这些技术中的任何一种在其他条件下都可能更有用 - 这就是为什么你不能做出任何确定性的声明,除了“你必须尝试一下”。
+第一个限制是内存大小;因为数组是预先分配的,所以我们不能创建几乎与以前版本一样大的任何东西。并行化可以加快速度,甚至比使用 **basicSum()** 循环更快。有趣的是, **Arrays.parallelPrefix()** 似乎实际上减慢了速度。但是,这些技术中的任何一种在其他条件下都可能更有用 - 这就是为什么你不能做出任何确定性的声明,除了“你必须尝试一下”。
-最后,考虑使用包装类**Long**的效果:
+最后,考虑使用包装类 **Long** 的效果:
```java
// concurrent/Summing3.java
@@ -499,9 +499,9 @@ Sum: 21ms
Long parallelPrefix: 3616ms
```
-现在可用的内存量大约减半,并且所有情况下所需的时间都会很长,除了**basicSum()**,它只是循环遍历数组。令人惊讶的是, **Arrays.parallelPrefix()** 比任何其他方法都要花费更长的时间。
+现在可用的内存量大约减半,并且所有情况下所需的时间都会很长,除了 **basicSum()** ,它只是循环遍历数组。令人惊讶的是, **Arrays.parallelPrefix()** 比任何其他方法都要花费更长的时间。
-我将 **parallel()** 版本分开了,因为在上面的程序中运行它导致了一个冗长的垃圾收集,扭曲了结果:
+我将 **parallel()** 版本分开了,因为在上面的程序中运行它导致了一个冗长的垃圾收集,扭曲了结果:
```java
// concurrent/Summing4.java
@@ -528,15 +528,15 @@ public class Summing4 {
Long Parallel: 1014ms
```
-它比非parallel()版本略快,但并不显着。
+它比非 parallel() 版本略快,但并不显着。
-导致时间增加的一个重要原因是处理器内存缓存。使用**Summing2.java**中的原始**long**,数组**la**是连续的内存。处理器可以更容易地预测该阵列的使用,并使缓存充满下一个需要的阵列元素。访问缓存比访问主内存快得多。似乎 **Long parallelPrefix** 计算受到影响,因为它为每个计算读取两个数组元素,并将结果写回到数组中,并且每个都为**Long**生成一个超出缓存的引用。
+导致时间增加的一个重要原因是处理器内存缓存。使用 **Summing2.java** 中的原始 **long** ,数组 **la** 是连续的内存。处理器可以更容易地预测该阵列的使用,并使缓存充满下一个需要的阵列元素。访问缓存比访问主内存快得多。似乎 **Long parallelPrefix** 计算受到影响,因为它为每个计算读取两个数组元素,并将结果写回到数组中,并且每个都为 **Long** 生成一个超出缓存的引用。
-使用**Summing3.java**和**Summing4.java**,**aL**是一个**Long**数组,它不是一个连续的数据数组,而是一个连续的**Long**对象引用数组。尽管该数组可能会在缓存中出现,但指向的对象几乎总是不在缓存中。
+使用 **Summing3.java** 和 **Summing4.java** ,**aL** 是一个 **Long** 数组,它不是一个连续的数据数组,而是一个连续的 **Long** 对象引用数组。尽管该数组可能会在缓存中出现,但指向的对象几乎总是不在缓存中。
-这些示例使用不同的SZ值来显示内存限制。
+这些示例使用不同的 SZ 值来显示内存限制。
-为了进行时间比较,以下是SZ设置为最小值1000万的结果:
+为了进行时间比较,以下是 SZ 设置为最小值 1000 万的结果:
**Sum Stream: 69msSum
Stream Parallel: 18msSum
@@ -548,15 +548,15 @@ parallelPrefix: 28ms
Long Array Stream Reduce: 1046ms
Long Basic Sum: 21ms
Long parallelPrefix: 3287ms
-Long Parallel: 1008ms**
+Long Parallel: 1008ms**
-虽然Java 8的各种内置“并行”工具非常棒,但我认为它们被视为神奇的灵丹妙药:“只需添加parallel()并且它会更快!” 我希望我已经开始表明情况并非所有都是如此,并且盲目地应用内置的“并行”操作有时甚至会使运行速度明显变慢。
+虽然 Java 8 的各种内置“并行”工具非常棒,但我认为它们被视为神奇的灵丹妙药:“只需添加 parallel() 并且它会更快!” 我希望我已经开始表明情况并非所有都是如此,并且盲目地应用内置的“并行”操作有时甚至会使运行速度明显变慢。
-- parallel()/limit()交点
+- parallel()/limit() 交点
-使用 **parallel()** 时会有更复杂的问题。从其他语言中吸取的流机制被设计为大约是一个无限的流模型。如果你拥有有限数量的元素,则可以使用集合以及为有限大小的集合设计的关联算法。如果你使用无限流,则使用针对流优化的算法。
+使用 **parallel()** 时会有更复杂的问题。从其他语言中吸取的流机制被设计为大约是一个无限的流模型。如果你拥有有限数量的元素,则可以使用集合以及为有限大小的集合设计的关联算法。如果你使用无限流,则使用针对流优化的算法。
-Java 8将两者合并起来。例如,**Collections**没有内置的**map()** 操作。在**Collection**和**Map**中唯一类似流的批处理操作是**forEach()** 。如果要执行**map()** 和**reduce()** 等操作,必须首先将**Collection**转换为存在这些操作的**Stream**:
+Java 8 将两者合并起来。例如,**Collections** 没有内置的 **map()** 操作。在 **Collection** 和 **Map** 中唯一类似流的批处理操作是 **forEach()** 。如果要执行 **map()** 和 **reduce()** 等操作,必须首先将 **Collection** 转换为存在这些操作的 **Stream** :
```java
// concurrent/CollectionIntoStream.java
@@ -595,9 +595,9 @@ bynxt
:PENCUXGVGINNLOZVEWPPCPOALJLNXT
```
-**Collection**确实有一些批处理操作,如**removeAll()**,**removeIf()** 和**retainAll()** ,但这些都是破坏性的操作。**ConcurrentHashMap**对**forEach**和**reduce**操作有特别广泛的支持。
+**Collection** 确实有一些批处理操作,如 **removeAll()** ,**removeIf()** 和 **retainAll()** ,但这些都是破坏性的操作。**ConcurrentHashMap** 对 **forEach** 和 **reduce** 操作有特别广泛的支持。
-在许多情况下,只在集合上调用**stream()** 或者**parallelStream()** 没有问题。但是,有时将**Stream**与**Collection**混合会产生意想不到的结果。这是一个有趣的难题:
+在许多情况下,只在集合上调用 **stream()** 或者 **parallelStream()** 没有问题。但是,有时将 **Stream** 与 **Collection** 混合会产生意想不到的结果。这是一个有趣的难题:
```java
// concurrent/ParallelStreamPuzzle.java
@@ -626,13 +626,13 @@ public class ParallelStreamPuzzle {
*/
```
-如果[1]注释运行它,它会产生预期的:
-**[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]**
-每次。但是包含了parallel(),它看起来像一个随机数生成器,带有输出(从一次运行到下一次运行不同),如:
-**[0, 3, 6, 8, 11, 14, 17, 20, 23, 26]**
+如果[1] 注释运行它,它会产生预期的:
+**[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]**
+每次。但是包含了 parallel(),它看起来像一个随机数生成器,带有输出(从一次运行到下一次运行不同),如:
+**[0, 3, 6, 8, 11, 14, 17, 20, 23, 26]**
这样一个简单的程序怎么会如此糟糕呢?让我们考虑一下我们在这里要实现的目标:“并行生成。”那意味着什么?一堆线程都在从一个生成器取值,然后以某种方式选择有限的结果集?代码看起来很简单,但它变成了一个特别棘手的问题。
-为了看到它,我们将添加一些仪器。由于我们正在处理线程,因此我们必须将任何跟踪信息捕获到并发数据结构中。在这里我使用**ConcurrentLinkedDeque**:
+为了看到它,我们将添加一些仪器。由于我们正在处理线程,因此我们必须将任何跟踪信息捕获到并发数据结构中。在这里我使用 **ConcurrentLinkedDeque** :
```java
// concurrent/ParallelStreamPuzzle2.java
@@ -672,9 +672,9 @@ public class ParallelStreamPuzzle2 {
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
```
-current是使用线程安全的 **AtomicInteger** 类定义的,可以防止竞争条件;**parallel()** 允许多个线程调用**get()**。
+current 是使用线程安全的 **AtomicInteger** 类定义的,可以防止竞争条件;**parallel()** 允许多个线程调用 **get()** 。
-在查看 **PSP2.txt** .**IntGenerator.get()** 被调用1024次时,你可能会感到惊讶。
+在查看 **PSP2.txt** .**IntGenerator.get()** 被调用 1024 次时,你可能会感到惊讶。
```
0: main
@@ -704,9 +704,9 @@ current是使用线程安全的 **AtomicInteger** 类定义的,可以防止竞
这个块大小似乎是内部实现的一部分(尝试使用`limit()` 的不同参数来查看不同的块大小)。将`parallel()`与`limit()`结合使用可以预取一串值,作为流输出。
-试着想象一下这里发生了什么:一个流抽象出无限序列,按需生成。当你要求它并行产生流时,你要求所有这些线程尽可能地调用`get()`。添加`limit()`,你说“只需要这些。”基本上,当你为了随机输出而选择将`parallel()`与`limit()`结合使用时,这种方法可能对你正在解决的问题有效。但是当你这样做时,你必须明白。这是一个仅限专家的功能,而不是要争辩说“Java弄错了”。
+试着想象一下这里发生了什么:一个流抽象出无限序列,按需生成。当你要求它并行产生流时,你要求所有这些线程尽可能地调用`get()`。添加`limit()`,你说“只需要这些。”基本上,当你为了随机输出而选择将`parallel()`与`limit()`结合使用时,这种方法可能对你正在解决的问题有效。但是当你这样做时,你必须明白。这是一个仅限专家的功能,而不是要争辩说“Java 弄错了”。
-什么是更合理的方法来解决问题?好吧,如果你想生成一个int流,你可以使用IntStream.range(),如下所示:
+什么是更合理的方法来解决问题?好吧,如果你想生成一个 int 流,你可以使用 IntStream.range(),如下所示:
```java
// concurrent/ParallelStreamPuzzle3.java
@@ -743,31 +743,31 @@ public class ParallelStreamPuzzle3 {
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
```
-为了表明**parallel()**确实有效,我添加了一个对**peek()** 的调用,这是一个主要用于调试的流函数:它从流中提取一个值并执行某些操作但不影响从流向下传递的元素。注意这会干扰线程行为,但我只是尝试在这里做一些事情,而不是实际调试任何东西。
+为了表明 **parallel()** 确实有效,我添加了一个对 **peek()** 的调用,这是一个主要用于调试的流函数:它从流中提取一个值并执行某些操作但不影响从流向下传递的元素。注意这会干扰线程行为,但我只是尝试在这里做一些事情,而不是实际调试任何东西。
-你还可以看到**boxed()** 的添加,它接受**int**流并将其转换为**Integer**流。
+你还可以看到 **boxed()** 的添加,它接受 **int** 流并将其转换为 **Integer** 流。
-现在我们得到多个线程产生不同的值,但它只产生10个请求的值,而不是1024个产生10个值。
+现在我们得到多个线程产生不同的值,但它只产生 10 个请求的值,而不是 1024 个产生 10 个值。
-它更快吗?一个更好的问题是:什么时候开始有意义?当然不是这么小的一套;上下文切换的代价远远超过并行性的任何加速。很难想象什么时候用并行生成一个简单的数字序列会有意义。如果你要生成的东西需要很高的成本,它可能有意义 - 但这都是猜测。只有通过测试我们才能知道用并行是否有效。记住这句格言:“首先使它工作,然后使它更快地工作 - 只有当你必须这样做时。”将**parallel()** 和**limit()** 结合使用仅供专家操作(把话说在前面,我不认为自己是这里的专家)。
+它更快吗?一个更好的问题是:什么时候开始有意义?当然不是这么小的一套;上下文切换的代价远远超过并行性的任何加速。很难想象什么时候用并行生成一个简单的数字序列会有意义。如果你要生成的东西需要很高的成本,它可能有意义 - 但这都是猜测。只有通过测试我们才能知道用并行是否有效。记住这句格言:“首先使它工作,然后使它更快地工作 - 只有当你必须这样做时。”将 **parallel()** 和 **limit()** 结合使用仅供专家操作(把话说在前面,我不认为自己是这里的专家)。
- 并行流只看起来很容易
-实际上,在许多情况下,并行流确实可以毫不费力地更快地产生结果。但正如你所见,仅仅将**parallel()** 加到你的Stream操作上并不一定是安全的事情。在使用**parallel()** 之前,你必须了解并行性如何帮助或损害你的操作。一个基本认知错误就是认为使用并行性总是一个好主意。事实上并不是。Stream意味着你不需要重写所有代码便可以并行运行它。但是流的出现并不意味着你可以不用理解并行的原理以及不用考虑并行是否真的有助于实现你的目标。
+实际上,在许多情况下,并行流确实可以毫不费力地更快地产生结果。但正如你所见,仅仅将 **parallel()** 加到你的 Stream 操作上并不一定是安全的事情。在使用 **parallel()** 之前,你必须了解并行性如何帮助或损害你的操作。一个基本认知错误就是认为使用并行性总是一个好主意。事实上并不是。Stream 意味着你不需要重写所有代码便可以并行运行它。但是流的出现并不意味着你可以不用理解并行的原理以及不用考虑并行是否真的有助于实现你的目标。
## 创建和运行任务
-如果无法通过并行流实现并发,则必须创建并运行自己的任务。稍后你将看到运行任务的理想Java 8方法是CompletableFuture,但我们将使用更基本的工具介绍概念。
+如果无法通过并行流实现并发,则必须创建并运行自己的任务。稍后你将看到运行任务的理想 Java 8 方法是 CompletableFuture,但我们将使用更基本的工具介绍概念。
-Java并发的历史始于非常原始和有问题的机制,并且充满了各种尝试的改进。这些主要归入附录:[低级并发(Appendix: Low-Level Concurrency)](./Appendix-Low-Level-Concurrency.md)。在这里,我们将展示一个规范形式,表示创建和运行任务的最简单,最好的方法。与并发中的所有内容一样,存在各种变体,但这些变体要么降级到该附录,要么超出本书的范围。
+Java 并发的历史始于非常原始和有问题的机制,并且充满了各种尝试的改进。这些主要归入附录:[低级并发 (Appendix: Low-Level Concurrency)](./Appendix-Low-Level-Concurrency.md)。在这里,我们将展示一个规范形式,表示创建和运行任务的最简单,最好的方法。与并发中的所有内容一样,存在各种变体,但这些变体要么降级到该附录,要么超出本书的范围。
- Tasks and Executors
-在Java的早期版本中,你通过直接创建自己的Thread对象来使用线程,甚至将它们子类化以创建你自己的特定“任务线程”对象。你手动调用了构造函数并自己启动了线程。
+在 Java 的早期版本中,你通过直接创建自己的 Thread 对象来使用线程,甚至将它们子类化以创建你自己的特定“任务线程”对象。你手动调用了构造函数并自己启动了线程。
-创建所有这些线程的开销变得非常重要,现在不鼓励采用手动操作方法。在Java 5中,添加了类来为你处理线程池。你可以将任务创建为单独的类型,然后将其交给ExecutorService以运行该任务,而不是为每种不同类型的任务创建新的Thread子类型。ExecutorService为你管理线程,并且在运行任务后重新循环线程而不是丢弃线程。
+创建所有这些线程的开销变得非常重要,现在不鼓励采用手动操作方法。在 Java 5 中,添加了类来为你处理线程池。你可以将任务创建为单独的类型,然后将其交给 ExecutorService 以运行该任务,而不是为每种不同类型的任务创建新的 Thread 子类型。ExecutorService 为你管理线程,并且在运行任务后重新循环线程而不是丢弃线程。
-首先,我们将创建一个几乎不执行任务的任务。它“sleep”(暂停执行)100毫秒,显示其标识符和正在执行任务的线程的名称,然后完成:
+首先,我们将创建一个几乎不执行任务的任务。它“sleep”(暂停执行)100 毫秒,显示其标识符和正在执行任务的线程的名称,然后完成:
```java
// concurrent/NapTask.java
@@ -790,7 +790,7 @@ public class NapTask implements Runnable {
}
```
-这只是一个**Runnable**:一个包含**run()** 方法的类。它没有包含实际运行任务的机制。我们使用**Nap**类中的“sleep”:
+这只是一个 **Runnable** :一个包含 **run()** 方法的类。它没有包含实际运行任务的机制。我们使用 **Nap** 类中的“sleep”:
```java
// onjava/Nap.java
@@ -812,11 +812,11 @@ public class Nap {
```
为了消除异常处理的视觉干扰,这被定义为实用程序。第二个构造函数在超时时显示一条消息
-对**TimeUnit.MILLISECONDS.sleep()** 的调用获取“当前线程”并在参数中将其置于休眠状态,这意味着该线程被挂起。这并不意味着底层处理器停止。操作系统将其切换到其他任务,例如在你的计算机上运行另一个窗口。OS任务管理器定期检查**sleep()** 是否超时。当它执行时,线程被“唤醒”并给予更多处理时间。
+对 **TimeUnit.MILLISECONDS.sleep()** 的调用获取“当前线程”并在参数中将其置于休眠状态,这意味着该线程被挂起。这并不意味着底层处理器停止。操作系统将其切换到其他任务,例如在你的计算机上运行另一个窗口。OS 任务管理器定期检查 **sleep()** 是否超时。当它执行时,线程被“唤醒”并给予更多处理时间。
-你可以看到**sleep()** 抛出一个受检的**InterruptedException**;这是原始Java设计中的一个工件,它通过突然断开它们来终止任务。因为它往往会产生不稳定的状态,所以后来不鼓励终止。但是,我们必须在需要或仍然发生终止的情况下捕获异常。
+你可以看到 **sleep()** 抛出一个受检的 **InterruptedException** ;这是原始 Java 设计中的一个工件,它通过突然断开它们来终止任务。因为它往往会产生不稳定的状态,所以后来不鼓励终止。但是,我们必须在需要或仍然发生终止的情况下捕获异常。
-要执行任务,我们将从最简单的方法--SingleThreadExecutor开始:
+要执行任务,我们将从最简单的方法--SingleThreadExecutor 开始:
```java
//concurrent/SingleThreadExecutor.java
@@ -869,13 +869,13 @@ main awaiting termination
NapTask[9] pool-1-thread-1
```
-首先请注意,没有**SingleThreadExecutor**类。**newSingleThreadExecutor()** 是 **Executors** 中的一个工厂方法,它创建特定类型的**ExecutorService**[^4]
+首先请注意,没有 **SingleThreadExecutor** 类。**newSingleThreadExecutor()** 是 **Executors** 中的一个工厂方法,它创建特定类型的 **ExecutorService** [^4]
-我创建了十个NapTasks并将它们提交给ExecutorService,这意味着它们开始自己运行。然而,在此期间,main()继续做事。当我运行callexec.shutdown()时,它告诉ExecutorService完成已经提交的任务,但不接受任何新任务。此时,这些任务仍然在运行,因此我们必须等到它们在退出main()之前完成。这是通过检查exec.isTerminated()来实现的,这在所有任务完成后变为true。
+我创建了十个 NapTasks 并将它们提交给 ExecutorService,这意味着它们开始自己运行。然而,在此期间,main() 继续做事。当我运行 callexec.shutdown() 时,它告诉 ExecutorService 完成已经提交的任务,但不接受任何新任务。此时,这些任务仍然在运行,因此我们必须等到它们在退出 main() 之前完成。这是通过检查 exec.isTerminated() 来实现的,这在所有任务完成后变为 true。
-请注意,main()中线程的名称是main,并且只有一个其他线程pool-1-thread-1。此外,交错输出显示两个线程确实同时运行。
+请注意,main() 中线程的名称是 main,并且只有一个其他线程 pool-1-thread-1。此外,交错输出显示两个线程确实同时运行。
-如果你只是调用exec.shutdown(),程序将完成所有任务。也就是说,不需要**while(!exec.isTerminated())**。
+如果你只是调用 exec.shutdown(),程序将完成所有任务。也就是说,不需要 **while(!exec.isTerminated())** 。
```java
// concurrent/SingleThreadExecutor2.java
@@ -908,7 +908,7 @@ NapTask[8] pool-1-thread-1
NapTask[9] pool-1-thread-1
```
-一旦你callexec.shutdown(),尝试提交新任务将抛出RejectedExecutionException。
+一旦你 callexec.shutdown(),尝试提交新任务将抛出 RejectedExecutionException。
```java
// concurrent/MoreTasksAfterShutdown.java
@@ -934,11 +934,11 @@ public class MoreTasksAfterShutdown {
java.util.concurrent.RejectedExecutionException: TaskNapTask[99] rejected from java.util.concurrent.ThreadPoolExecutor@4e25154f[Shutting down, pool size = 1,active threads = 1, queued tasks = 0, completed tasks =0]NapTask[1] pool-1-thread-1
```
-**exec.shutdown()** 的替代方法是**exec.shutdownNow()** ,它除了不接受新任务外,还会尝试通过中断任务来停止任何当前正在运行的任务。同样,中断是错误的,容易出错并且不鼓励。
+**exec.shutdown()** 的替代方法是 **exec.shutdownNow()** ,它除了不接受新任务外,还会尝试通过中断任务来停止任何当前正在运行的任务。同样,中断是错误的,容易出错并且不鼓励。
- 使用更多线程
-使用线程的重点是(几乎总是)更快地完成任务,那么我们为什么要限制自己使用SingleThreadExecutor呢?查看执行**Executors**的Javadoc,你将看到更多选项。例如CachedThreadPool:
+使用线程的重点是(几乎总是)更快地完成任务,那么我们为什么要限制自己使用 SingleThreadExecutor 呢?查看执行 **Executors** 的 Javadoc,你将看到更多选项。例如 CachedThreadPool:
```java
// concurrent/CachedThreadPool.java
@@ -971,7 +971,7 @@ NapTask[6] pool-1-thread-7
NapTask[5] pool-1-thread-6
```
-当你运行这个程序时,你会发现它完成得更快。这是有道理的,每个任务都有自己的线程,所以它们都并行运行,而不是使用相同的线程来顺序运行每个任务。这似乎没毛病,很难理解为什么有人会使用SingleThreadExecutor。
+当你运行这个程序时,你会发现它完成得更快。这是有道理的,每个任务都有自己的线程,所以它们都并行运行,而不是使用相同的线程来顺序运行每个任务。这似乎没毛病,很难理解为什么有人会使用 SingleThreadExecutor。
要理解这个问题,我们需要一个更复杂的任务:
@@ -994,7 +994,7 @@ public class InterferingTask implements Runnable {
```
-每个任务增加val一百次。这似乎很简单。让我们用CachedThreadPool尝试一下:
+每个任务增加 val 一百次。这似乎很简单。让我们用 CachedThreadPool 尝试一下:
```java
// concurrent/CachedThreadPool2.java
@@ -1027,7 +1027,7 @@ public class CachedThreadPool2 {
6 pool-1-thread-7 1000
```
-输出不是我们所期望的,并且从一次运行到下一次运行会有所不同。问题是所有的任务都试图写入val的单个实例,并且他们正在踩着彼此的脚趾。我们称这样的类是线程不安全的。让我们看看SingleThreadExecutor会发生什么:
+输出不是我们所期望的,并且从一次运行到下一次运行会有所不同。问题是所有的任务都试图写入 val 的单个实例,并且他们正在踩着彼此的脚趾。我们称这样的类是线程不安全的。让我们看看 SingleThreadExecutor 会发生什么:
```java
// concurrent/SingleThreadExecutor3.java
@@ -1060,15 +1060,15 @@ public class SingleThreadExecutor3 {
9 pool-1-thread-1 1000
```
-现在我们每次都得到一致的结果,尽管**InterferingTask**缺乏线程安全性。这是SingleThreadExecutor的主要好处 - 因为它一次运行一个任务,这些任务不会相互干扰,因此强加了线程安全性。这种现象称为线程封闭,因为在单线程上运行任务限制了它们的影响。线程封闭限制了加速,但可以节省很多困难的调试和重写。
+现在我们每次都得到一致的结果,尽管 **InterferingTask** 缺乏线程安全性。这是 SingleThreadExecutor 的主要好处 - 因为它一次运行一个任务,这些任务不会相互干扰,因此强加了线程安全性。这种现象称为线程封闭,因为在单线程上运行任务限制了它们的影响。线程封闭限制了加速,但可以节省很多困难的调试和重写。
- 产生结果
-因为**InterferingTask**是一个**Runnable**,它没有返回值,因此只能使用副作用产生结果 - 操纵缓冲值而不是返回结果。副作用是并发编程中的主要问题之一,因为我们看到了**CachedThreadPool2.java**。**InterferingTask**中的**val**被称为可变共享状态,这就是问题所在:多个任务同时修改同一个变量会产生竞争。结果取决于首先在终点线上执行哪个任务,并修改变量(以及其他可能性的各种变化)。
+因为 **InterferingTask** 是一个 **Runnable** ,它没有返回值,因此只能使用副作用产生结果 - 操纵缓冲值而不是返回结果。副作用是并发编程中的主要问题之一,因为我们看到了 **CachedThreadPool2.java** 。**InterferingTask** 中的 **val** 被称为可变共享状态,这就是问题所在:多个任务同时修改同一个变量会产生竞争。结果取决于首先在终点线上执行哪个任务,并修改变量(以及其他可能性的各种变化)。
避免竞争条件的最好方法是避免可变的共享状态。我们可以称之为自私的孩子原则:什么都不分享。
-使用**InterferingTask**,最好删除副作用并返回任务结果。为此,我们创建**Callable**而不是**Runnable**:
+使用 **InterferingTask** ,最好删除副作用并返回任务结果。为此,我们创建 **Callable** 而不是 **Runnable** :
```java
// concurrent/CountingTask.java
@@ -1089,9 +1089,9 @@ public class CountingTask implements Callable {
```
-**call()完全独立于所有其他CountingTasks生成其结果**,这意味着没有可变的共享状态
+**call() 完全独立于所有其他 CountingTasks 生成其结果**,这意味着没有可变的共享状态
-**ExecutorService**允许你使用**invokeAll()**启动集合中的每个Callable:
+**ExecutorService** 允许你使用 **invokeAll()** 启动集合中的每个 Callable:
```java
// concurrent/CachedThreadPool3.java
@@ -1141,7 +1141,7 @@ sum = 1000
```
-只有在所有任务完成后,**invokeAll()**才会返回一个**Future**列表,每个任务一个**Future**。**Future**是Java 5中引入的机制,允许你提交任务而无需等待它完成。在这里,我们使用**ExecutorService.submit()**:
+只有在所有任务完成后,**invokeAll()** 才会返回一个 **Future** 列表,每个任务一个 **Future** 。**Future** 是 Java 5 中引入的机制,允许你提交任务而无需等待它完成。在这里,我们使用 **ExecutorService.submit()** :
```java
// concurrent/Futures.java
@@ -1167,15 +1167,15 @@ public class Futures {
100
```
-- [1] 当你的任务在尚未完成的**Future**上调用**get()**时,调用会阻塞(等待)直到结果可用。
+- [1] 当你的任务在尚未完成的 **Future** 上调用 **get()** 时,调用会阻塞(等待)直到结果可用。
-但这意味着,在**CachedThreadPool3.java**中,**Future**似乎是多余的,因为**invokeAll()**甚至在所有任务完成之前都不会返回。但是,这里的Future并不用于延迟结果,而是用于捕获任何可能发生的异常。
+但这意味着,在 **CachedThreadPool3.java** 中,**Future** 似乎是多余的,因为 **invokeAll()** 甚至在所有任务完成之前都不会返回。但是,这里的 Future 并不用于延迟结果,而是用于捕获任何可能发生的异常。
-还要注意在**CachedThreadPool3.java.get()**中抛出异常,因此**extractResult()**在Stream中执行此提取。
+还要注意在 **CachedThreadPool3.java.get()** 中抛出异常,因此 **extractResult()** 在 Stream 中执行此提取。
-因为当你调用**get()**时,**Future**会阻塞,所以它只能解决等待任务完成才暴露问题。最终,**Futures**被认为是一种无效的解决方案,现在不鼓励,我们推荐Java 8的**CompletableFuture**,这将在本章后面探讨。当然,你仍会在遗留库中遇到Futures。
+因为当你调用 **get()** 时,**Future** 会阻塞,所以它只能解决等待任务完成才暴露问题。最终,**Futures** 被认为是一种无效的解决方案,现在不鼓励,我们推荐 Java 8 的 **CompletableFuture** ,这将在本章后面探讨。当然,你仍会在遗留库中遇到 Futures。
-我们可以使用并行Stream以更简单,更优雅的方式解决这个问题:
+我们可以使用并行 Stream 以更简单,更优雅的方式解决这个问题:
```java
// concurrent/CountingStream.java
@@ -1213,9 +1213,9 @@ public class CountingStream {
这不仅更容易理解,而且我们需要做的就是将 `parallel()` 插入到其他顺序操作中,然后一切都在同时运行。
-- Lambda和方法引用作为任务
+- Lambda 和方法引用作为任务
-在 **java8** 有了 **lambdas** 和方法引用,你不需要受限于只能使用 **Runnable** 和 **Callable** 。因为 java8 的**lambdas** 和方法引用可以通过匹配方法签名来使用(即,它支持结构一致性),所以我们可以将非 **Runnable** 或 **Callable** 的参数传递给 `ExecutorService` :
+在 **java8** 有了 **lambdas** 和方法引用,你不需要受限于只能使用 **Runnable** 和 **Callable** 。因为 java8 的 **lambdas** 和方法引用可以通过匹配方法签名来使用(即,它支持结构一致性),所以我们可以将非 **Runnable** 或 **Callable** 的参数传递给 `ExecutorService` :
```java
// concurrent/LambdasAndMethodReferences.java
@@ -1257,24 +1257,24 @@ Lambda2
```
-这里,前两个**submit()**调用可以改为调用**execute()**。所有**submit()**调用都返回**Futures**,你可以在后两次调用的情况下提取结果。
+这里,前两个 **submit()** 调用可以改为调用 **execute()** 。所有 **submit()** 调用都返回 **Futures** ,你可以在后两次调用的情况下提取结果。
## 终止耗时任务
-并发程序通常使用长时间运行的任务。可调用任务在完成时返回值;虽然这给它一个有限的寿命,但仍然可能很长。可运行的任务有时被设置为永远运行的后台进程。你经常需要一种方法在正常完成之前停止**Runnable**和**Callable**任务,例如当你关闭程序时。
+并发程序通常使用长时间运行的任务。可调用任务在完成时返回值;虽然这给它一个有限的寿命,但仍然可能很长。可运行的任务有时被设置为永远运行的后台进程。你经常需要一种方法在正常完成之前停止 **Runnable** 和 **Callable** 任务,例如当你关闭程序时。
-最初的Java设计提供了中断运行任务的机制(为了向后兼容,仍然存在);中断机制包括阻塞问题。中断任务既乱又复杂,因为你必须了解可能发生中断的所有可能状态,以及可能导致的数据丢失。使用中断被视为反对模式,但我们仍然被迫接受。
+最初的 Java 设计提供了中断运行任务的机制(为了向后兼容,仍然存在);中断机制包括阻塞问题。中断任务既乱又复杂,因为你必须了解可能发生中断的所有可能状态,以及可能导致的数据丢失。使用中断被视为反对模式,但我们仍然被迫接受。
InterruptedException,因为设计的向后兼容性残留。
-任务终止的最佳方法是设置任务周期性检查的标志。然后任务可以通过自己的shutdown进程并正常终止。不是在任务中随机关闭线程,而是要求任务在到达了一个较好时自行终止。这总是产生比中断更好的结果,以及更容易理解的更合理的代码。
+任务终止的最佳方法是设置任务周期性检查的标志。然后任务可以通过自己的 shutdown 进程并正常终止。不是在任务中随机关闭线程,而是要求任务在到达了一个较好时自行终止。这总是产生比中断更好的结果,以及更容易理解的更合理的代码。
-以这种方式终止任务听起来很简单:设置任务可以看到的**boolean** flag。编写任务,以便定期检查标志并执行正常终止。这实际上就是你所做的,但是有一个复杂的问题:我们的旧克星,共同的可变状态。如果该标志可以被另一个任务操纵,则存在碰撞可能性。
+以这种方式终止任务听起来很简单:设置任务可以看到的 **boolean** flag。编写任务,以便定期检查标志并执行正常终止。这实际上就是你所做的,但是有一个复杂的问题:我们的旧克星,共同的可变状态。如果该标志可以被另一个任务操纵,则存在碰撞可能性。
-在研究Java文献时,你会发现很多解决这个问题的方法,经常使用**volatile**关键字。我们将使用更简单的技术并避免所有易变的参数,这些都在[附录:低级并发](./Appendix-Low-Level-Concurrency.md)中有所涉及。
+在研究 Java 文献时,你会发现很多解决这个问题的方法,经常使用 **volatile** 关键字。我们将使用更简单的技术并避免所有易变的参数,这些都在[附录:低级并发 ](./Appendix-Low-Level-Concurrency.md) 中有所涉及。
-Java 5引入了**Atomic**类,它提供了一组可以使用的类型,而不必担心并发问题。我们将添加**AtomicBoolean**标志,告诉任务清理自己并退出。
+Java 5 引入了 **Atomic** 类,它提供了一组可以使用的类型,而不必担心并发问题。我们将添加 **AtomicBoolean** 标志,告诉任务清理自己并退出。
```java
// concurrent/QuittableTask.java
@@ -1299,14 +1299,14 @@ public class QuittableTask implements Runnable {
```
-虽然多个任务可以在同一个实例上成功调用**quit()**,但是**AtomicBoolean**可以防止多个任务同时实际修改**running**,从而使**quit()**方法成为线程安全的。
+虽然多个任务可以在同一个实例上成功调用 **quit()** ,但是 **AtomicBoolean** 可以防止多个任务同时实际修改 **running** ,从而使 **quit()** 方法成为线程安全的。
-- [1]:只要运行标志为true,此任务的run()方法将继续。
+- [1]:只要运行标志为 true,此任务的 run() 方法将继续。
- [2]: 显示仅在任务退出时发生。
-需要**running AtomicBoolean**证明编写Java program并发时最基本的困难之一是,如果**running**是一个普通的布尔值,你可能无法在执行程序中看到问题。实际上,在这个例子中,你可能永远不会有任何问题 - 但是代码仍然是不安全的。编写表明该问题的测试可能很困难或不可能。因此,你没有任何反馈来告诉你已经做错了。通常,你编写线程安全代码的唯一方法就是通过了解事情可能出错的所有细微之处。
+需要 **running AtomicBoolean** 证明编写 Java program 并发时最基本的困难之一是,如果 **running** 是一个普通的布尔值,你可能无法在执行程序中看到问题。实际上,在这个例子中,你可能永远不会有任何问题 - 但是代码仍然是不安全的。编写表明该问题的测试可能很困难或不可能。因此,你没有任何反馈来告诉你已经做错了。通常,你编写线程安全代码的唯一方法就是通过了解事情可能出错的所有细微之处。
-作为测试,我们将启动很多QuittableTasks然后关闭它们。尝试使用较大的COUNT值
+作为测试,我们将启动很多 QuittableTasks 然后关闭它们。尝试使用较大的 COUNT 值
```java
// concurrent/QuittingTasks.java
@@ -1337,11 +1337,11 @@ public class QuittingTasks {
136 131 135 139 148 140 2 126 6 5 1 18 129 17 14 13 2122 9 10 30 33 58 37 125 26 34 133 145 78 137 141 138 6274 142 86 65 73 146 70 42 149 121 110 134 105 82 117106 113 122 45 114 118 38 50 29 90 101 89 57 53 94 4161 66 130 69 77 81 85 93 25 102 54 109 98 49 46 97
```
-我使用**peek()**将**QuittableTasks**传递给**ExecutorService**,然后将这些任务收集到**List.main()**中,只要任何任务仍在运行,就会阻止程序退出。即使为每个任务按顺序调用quit()方法,任务也不会按照它们创建的顺序关闭。独立运行的任务不会确定性地响应信号。
+我使用 **peek()** 将 **QuittableTasks** 传递给 **ExecutorService** ,然后将这些任务收集到 **List.main()** 中,只要任何任务仍在运行,就会阻止程序退出。即使为每个任务按顺序调用 quit() 方法,任务也不会按照它们创建的顺序关闭。独立运行的任务不会确定性地响应信号。
-## CompletableFuture类
+## CompletableFuture 类
-作为介绍,这里是使用CompletableFutures在QuittingTasks.java中:
+作为介绍,这里是使用 CompletableFutures 在 QuittingTasks.java 中:
```java
// concurrent/QuittingCompletable.java
@@ -1380,7 +1380,7 @@ public class QuittingCompletable {
### 基本用法
-这是一个带有静态方法**work()**的类,它对该类的对象执行某些工作:
+这是一个带有静态方法 **work()** 的类,它对该类的对象执行某些工作:
```java
// concurrent/Machina.java
@@ -1415,9 +1415,9 @@ public class Machina {
```
-这是一个有限状态机,一个微不足道的机器,因为它没有分支......它只是从头到尾遍历一条路径。**work()**方法将机器从一个状态移动到下一个状态,并且需要100毫秒才能完成“工作”。
+这是一个有限状态机,一个微不足道的机器,因为它没有分支......它只是从头到尾遍历一条路径。**work()** 方法将机器从一个状态移动到下一个状态,并且需要 100 毫秒才能完成“工作”。
-**CompletableFuture**可以被用来做的一件事是, 使用**completedFuture()**将它感兴趣的对象进行包装。
+**CompletableFuture** 可以被用来做的一件事是, 使用 **completedFuture()** 将它感兴趣的对象进行包装。
```java
// concurrent/CompletedMachina.java
@@ -1437,11 +1437,11 @@ public class CompletedMachina {
}
```
-**completedFuture()**创建一个“已经完成”的**CompletableFuture**。对这样一个未来做的唯一有用的事情是**get()**里面的对象,所以这看起来似乎没有用。注意**CompletableFuture**被输入到它包含的对象。这个很重要。
+**completedFuture()** 创建一个“已经完成”的 **CompletableFuture** 。对这样一个未来做的唯一有用的事情是 **get()** 里面的对象,所以这看起来似乎没有用。注意 **CompletableFuture** 被输入到它包含的对象。这个很重要。
-通常,**get()**在等待结果时阻塞调用线程。此块可以通过**InterruptedException**或**ExecutionException**中断。在这种情况下,阻止永远不会发生,因为CompletableFutureis已经完成,所以答案立即可用。
+通常,**get()** 在等待结果时阻塞调用线程。此块可以通过 **InterruptedException** 或 **ExecutionException** 中断。在这种情况下,阻止永远不会发生,因为 CompletableFutureis 已经完成,所以答案立即可用。
-当我们将**handle()**包装在**CompletableFuture**中时,发现我们可以在**CompletableFuture**上添加操作来处理所包含的对象,使得事情变得更加有趣:
+当我们将 **handle()** 包装在 **CompletableFuture** 中时,发现我们可以在 **CompletableFuture** 上添加操作来处理所包含的对象,使得事情变得更加有趣:
```java
// concurrent/CompletableApply.java
@@ -1472,11 +1472,11 @@ Machina0: THREE
Machina0: complete
```
-`thenApply()` 应用一个接收输入并产生输出的函数。在本例中,`work()` 函数产生的类型与它所接收的类型相同 (`Machina`),因此每个 `CompletableFuture`添加的操作的返回类型都为 `Machina`,但是(类似于流中的 `map()` )函数也可以返回不同的类型,这将体现在返回类型上。
+`thenApply()` 应用一个接收输入并产生输出的函数。在本例中,`work()` 函数产生的类型与它所接收的类型相同 (`Machina`),因此每个 `CompletableFuture`添加的操作的返回类型都为 `Machina`,但是 (类似于流中的 `map()` ) 函数也可以返回不同的类型,这将体现在返回类型上。
-你可以在此处看到有关**CompletableFutures**的重要信息:它们会在你执行操作时自动解包并重新包装它们所携带的对象。这使得编写和理解代码变得更加简单, 而不会在陷入在麻烦的细节中。
+你可以在此处看到有关 **CompletableFutures** 的重要信息:它们会在你执行操作时自动解包并重新包装它们所携带的对象。这使得编写和理解代码变得更加简单, 而不会在陷入在麻烦的细节中。
-我们可以消除中间变量并将操作链接在一起,就像我们使用Streams一样:
+我们可以消除中间变量并将操作链接在一起,就像我们使用 Streams 一样:
```java
// concurrent/CompletableApplyChained.javaimport java.util.concurrent.*;
@@ -1507,9 +1507,9 @@ Machina0: complete
```
这里我们还添加了一个 `Timer`,它的功能在每一步都显性地增加 100ms 等待时间之外,还将 `CompletableFuture` 内部 `thenApply` 带来的额外开销给体现出来了。
-**CompletableFutures** 的一个重要好处是它们鼓励使用私有子类原则(不共享任何东西)。默认情况下,使用 **thenApply()** 来应用一个不对外通信的函数 - 它只需要一个参数并返回一个结果。这是函数式编程的基础,并且它在并发特性方面非常有效[^5]。并行流和 `ComplempleFutures` 旨在支持这些原则。只要你不决定共享数据(共享非常容易导致意外发生)你就可以编写出相对安全的并发程序。
+**CompletableFutures** 的一个重要好处是它们鼓励使用私有子类原则(不共享任何东西)。默认情况下,使用 **thenApply()** 来应用一个不对外通信的函数 - 它只需要一个参数并返回一个结果。这是函数式编程的基础,并且它在并发特性方面非常有效[^5]。并行流和 `ComplempleFutures` 旨在支持这些原则。只要你不决定共享数据(共享非常容易导致意外发生)你就可以编写出相对安全的并发程序。
-回调 `thenApply()` 一旦开始一个操作,在完成所有任务之前,不会完成 **CompletableFuture** 的构建。虽然这有时很有用,但是开始所有任务通常更有价值,这样就可以运行继续前进并执行其他操作。我们可通过`thenApplyAsync()` 来实现此目的:
+回调 `thenApply()` 一旦开始一个操作,在完成所有任务之前,不会完成 **CompletableFuture** 的构建。虽然这有时很有用,但是开始所有任务通常更有价值,这样就可以运行继续前进并执行其他操作。我们可通过`thenApplyAsync()` 来实现此目的:
```java
// concurrent/CompletableApplyAsync.java
@@ -1544,9 +1544,9 @@ Machina0: complete
552
```
-同步调用(我们通常使用的那种)意味着:“当你完成工作时,才返回”,而异步调用以意味着: “立刻返回并继续后续工作”。 正如你所看到的,`cf` 的创建现在发生的更快。每次调用 `thenApplyAsync()` 都会立刻返回,因此可以进行下一次调用,整个调用链路完成速度比以前快得多。
+同步调用 (我们通常使用的那种) 意味着:“当你完成工作时,才返回”,而异步调用以意味着: “立刻返回并继续后续工作”。 正如你所看到的,`cf` 的创建现在发生的更快。每次调用 `thenApplyAsync()` 都会立刻返回,因此可以进行下一次调用,整个调用链路完成速度比以前快得多。
-事实上,如果没有回调 `cf.join()` 方法,程序会在完成其工作之前退出。而 `cf.join()` 直到cf操作完成之前,阻止 `main()` 进程结束。我们还可以看出本示例大部分时间消耗在 `cf.join()` 这。
+事实上,如果没有回调 `cf.join()` 方法,程序会在完成其工作之前退出。而 `cf.join()` 直到 cf 操作完成之前,阻止 `main()` 进程结束。我们还可以看出本示例大部分时间消耗在 `cf.join()` 这。
这种“立即返回”的异步能力需要 `CompletableFuture` 库进行一些秘密(`client` 无感)工作。特别是,它将你需要的操作链存储为一组回调。当操作的第一个链路(后台操作)完成并返回时,第二个链路(后台操作)必须获取生成的 `Machina` 并开始工作,以此类推! 但这种异步机制没有我们可以通过程序调用栈控制的普通函数调用序列,它的调用链路顺序会丢失,因此它使用一个函数地址来存储的回调来解决这个问题。
@@ -1554,9 +1554,9 @@ Machina0: complete
- 其他操作
-当你查看`CompletableFuture`的 `Javadoc` 时,你会看到它有很多方法,但这个方法的大部分来自不同操作的变体。例如,有 `thenApply()`,`thenApplyAsync()` 和第二种形式的 `thenApplyAsync()`,它们使用 `Executor` 来运行任务(在本书中,我们忽略了 `Executor` 选项)。
+当你查看`CompletableFuture`的 `Javadoc` 时,你会看到它有很多方法,但这个方法的大部分来自不同操作的变体。例如,有 `thenApply()`,`thenApplyAsync()` 和第二种形式的 `thenApplyAsync()`,它们使用 `Executor` 来运行任务 (在本书中,我们忽略了 `Executor` 选项)。
-下面的示例展示了所有"基本"操作,这些操作既不涉及组合两个 `CompletableFuture`,也不涉及异常(我们将在后面介绍)。首先,为了提供简洁性和方便性,我们应该重用以下两个实用程序:
+下面的示例展示了所有"基本"操作,这些操作既不涉及组合两个 `CompletableFuture`,也不涉及异常 (我们将在后面介绍)。首先,为了提供简洁性和方便性,我们应该重用以下两个实用程序:
```java
package onjava;
@@ -1683,8 +1683,8 @@ dependents: 2
- `cfi(8)` 使用 `toCompletableFuture()` 从 `CompletionStage` 生成一个`CompletableFuture`。
- `c.complete(9)` 显示了如何通过给它一个结果来完成一个`task`(`future`)(与 `obtrudeValue()` 相对,后者可能会迫使其结果替换该结果)。
- 如果你调用 `CompletableFuture`中的 `cancel()`方法,如果已经完成此任务,则正常结束。 如果尚未完成,则使用 `CancellationException` 完成此 `CompletableFuture`。
- - 如果任务(`future`)完成,则**getNow()**方法返回`CompletableFuture`的完成值,否则返回`getNow()`的替换参数。
- - 最后,我们看一下依赖(`dependents`)的概念。如果我们将两个`thenApplyAsync()`调用链路到`CompletableFuture`上,则依赖项的数量不会增加,保持为1。但是,如果我们另外将另一个`thenApplyAsync()`直接附加到`c`,则现在有两个依赖项:两个一起的链路和另一个单独附加的链路。
+ - 如果任务(`future`)完成,则 **getNow()** 方法返回`CompletableFuture`的完成值,否则返回`getNow()`的替换参数。
+ - 最后,我们看一下依赖 (`dependents`) 的概念。如果我们将两个`thenApplyAsync()`调用链路到`CompletableFuture`上,则依赖项的数量不会增加,保持为 1。但是,如果我们另外将另一个`thenApplyAsync()`直接附加到`c`,则现在有两个依赖项:两个一起的链路和另一个单独附加的链路。
- 这表明你可以使用一个`CompletionStage`,当它完成时,可以根据其结果派生多个新任务。
@@ -1730,7 +1730,7 @@ public class Workable {
}
```
-在 `make()`中,`work()`方法应用于`CompletableFuture`。`work()`需要一定的时间才能完成,然后它将字母W附加到id上,表示工作已经完成。
+在 `make()`中,`work()`方法应用于`CompletableFuture`。`work()`需要一定的时间才能完成,然后它将字母 W 附加到 id 上,表示工作已经完成。
现在我们可以创建多个竞争的 `CompletableFuture`,并使用 `CompletableFuture` 库中的各种方法来进行操作:
@@ -1859,7 +1859,7 @@ thenAcceptBoth: Workable[AW], Workable[BW]
- `init()`方法用于 `A`, `B` 初始化这两个变量,因为 `B` 总是给出比`A`较短的延迟,所以总是 `win` 的一方。
- `join()` 是在两个方法上调用 `join()` 并显示边框的另一个便利方法。
- 所有这些 “`dual`” 方法都以一个 `CompletableFuture` 作为调用该方法的对象,第二个 `CompletableFuture` 作为第一个参数,然后是要执行的操作。
-- 通过使用 `showr()` 和 `voidr()` 可以看到,“`run`”和“`accept`”是终端操作,而“`apply`”和“`combine`”则生成新的 `payload-bearing` (承载负载)的 `CompletableFuture`。
+- 通过使用 `showr()` 和 `voidr()` 可以看到,“`run`”和“`accept`”是终端操作,而“`apply`”和“`combine`”则生成新的 `payload-bearing` (承载负载) 的 `CompletableFuture`。
- 方法的名称不言自明,你可以通过查看输出来验证这一点。一个特别有趣的方法是 `combineAsync()`,它等待两个 `CompletableFuture` 完成,然后将它们都交给一个 `BiFunction`,这个 `BiFunction` 可以将结果加入到最终的 `CompletableFuture` 的有效负载中。
@@ -2114,7 +2114,7 @@ done? false
java.lang.RuntimeException: forced
```
-测试 `A` 到 `E` 运行到抛出异常,然后…并没有将抛出的异常暴露给调用方。只有在测试F中调用 `get()` 时,我们才会看到抛出的异常。
+测试 `A` 到 `E` 运行到抛出异常,然后…并没有将抛出的异常暴露给调用方。只有在测试 F 中调用 `get()` 时,我们才会看到抛出的异常。
测试 `G` 表明,你可以首先检查在处理期间是否抛出异常,而不抛出该异常。然而,test `H` 告诉我们,不管异常是否成功,它仍然被视为已“完成”。
代码的最后一部分展示了如何将异常插入到 `CompletableFuture` 中,而不管是否存在任何失败。
在连接或获取结果时,我们使用 `CompletableFuture` 提供的更复杂的机制来自动响应异常,而不是使用粗糙的 `try-catch`。
@@ -2208,16 +2208,16 @@ result: Breakable_whenComplete [-4]
- `exceptionally()` 通过将一个好的对象插入到流中来恢复到一个可行的状态。
-- `handle()` 一致被调用来查看是否发生异常(必须检查fail是否为true)。
+- `handle()` 一致被调用来查看是否发生异常(必须检查 fail 是否为 true)。
- 但是 `handle()` 可以生成任何新类型,所以它允许执行处理,而不是像使用 `exceptionally()`那样简单地恢复。
- - `whenComplete()` 类似于handle(),同样必须测试它是否失败,但是参数是一个消费者,并且不修改传递给它的结果对象。
+ - `whenComplete()` 类似于 handle(),同样必须测试它是否失败,但是参数是一个消费者,并且不修改传递给它的结果对象。
### 流异常(Stream Exception)
-通过修改**CompletableExceptions.java**,看看 **CompletableFuture**异常与流异常有何不同:
+通过修改 **CompletableExceptions.java** ,看看 **CompletableFuture** 异常与流异常有何不同:
```java
// concurrent/StreamExceptions.java
@@ -2261,7 +2261,7 @@ Throwing Exception for C
Breakable_C failed
```
-使用 `CompletableFuture`,我们可以看到测试A到E的进展,但是使用流,在你应用一个终端操作之前(e.g. `forEach()`),什么都不会暴露给 Client
+使用 `CompletableFuture`,我们可以看到测试 A 到 E 的进展,但是使用流,在你应用一个终端操作之前(e.g. `forEach()`),什么都不会暴露给 Client
`CompletableFuture` 执行工作并捕获任何异常供以后检索。比较这两者并不容易,因为 `Stream` 在没有终端操作的情况下根本不做任何事情——但是流绝对不会存储它的异常。
@@ -2316,7 +2316,7 @@ public class ThrowsChecked {
}
```
-如果你试图像使用 `nochecked()` 那样使用` withchecked()` 的方法引用,编译器会在 `[1]` 和 `[2]` 中报错。相反,你必须写出lambda表达式(或者编写一个不会抛出异常的包装器方法)。
+如果你试图像使用 `nochecked()` 那样使用` withchecked()` 的方法引用,编译器会在 `[1]` 和 `[2]` 中报错。相反,你必须写出 lambda 表达式 (或者编写一个不会抛出异常的包装器方法)。
## 死锁
@@ -2325,7 +2325,7 @@ public class ThrowsChecked {
埃德斯·迪克斯特拉(`Essger Dijkstra`)发明的“哲学家进餐"问题是经典的死锁例证。基本描述指定了五位哲学家(此处显示的示例允许任何数目)。这些哲学家将花部分时间思考,花部分时间就餐。他们在思考的时候并不需要任何共享资源;但是他们使用的餐具数量有限。在最初的问题描述中,餐具是叉子,需要两个叉子才能从桌子中间的碗里取出意大利面。常见的版本是使用筷子, 显然,每个哲学家都需要两根筷子才能吃饭。
引入了一个困难:作为哲学家,他们的钱很少,所以他们只能买五根筷子(更一般地讲,筷子的数量与哲学家相同)。他们围在桌子周围,每人之间放一根筷子。 当一个哲学家要就餐时,该哲学家必须同时持有左边和右边的筷子。如果任一侧的哲学家都在使用所需的筷子,则我们的哲学家必须等待,直到可得到必须的筷子。
-**StickHolder** 类通过将单根筷子保持在大小为1的**BlockingQueue**中来管理它。**BlockingQueue**是一个设计用于在并发程序中安全使用的集合,如果你调用take()并且队列为空,则它将阻塞(等待)。将新元素放入队列后,将释放该块并返回该值:
+**StickHolder** 类通过将单根筷子保持在大小为 1 的 **BlockingQueue** 中来管理它。**BlockingQueue** 是一个设计用于在并发程序中安全使用的集合,如果你调用 take() 并且队列为空,则它将阻塞(等待)。将新元素放入队列后,将释放该块并返回该值:
```java
// concurrent/StickHolder.java
@@ -2399,7 +2399,7 @@ public class Philosopher implements Runnable {
}
```
-没有两个哲学家可以同时成功调用take()同一只筷子。另外,如果一个哲学家已经拿过筷子,那么下一个试图拿起同一根筷子的哲学家将阻塞,等待其被释放。
+没有两个哲学家可以同时成功调用 take() 同一只筷子。另外,如果一个哲学家已经拿过筷子,那么下一个试图拿起同一根筷子的哲学家将阻塞,等待其被释放。
结果是一个看似无辜的程序陷入了死锁。我在这里使用数组而不是集合,只是因为这种语法更简洁:
@@ -2439,19 +2439,19 @@ public class DiningPhilosophers {
```
- 当你停止查看输出时,该程序将死锁。但是,根据你的计算机配置,你可能不会看到死锁。看来这取决于计算机上的内核数[^7]。两个核心不会产生死锁,但两核以上却很容易产生死锁。
-- 此行为使该示例更好地说明了死锁,因为你可能正在具有2核的计算机上编写程序(如果确实是导致问题的原因),并且确信该程序可以正常工作,只能启动它将其安装在另一台计算机上时出现死锁。请注意,不能因为你没或不容易看到死锁,这并不意味着此程序不会在2核机器上发生死锁。 该程序仍然有死锁倾向,只是很少发生——可以说是最糟糕的情况,因为问题不容易出现。
+- 此行为使该示例更好地说明了死锁,因为你可能正在具有 2 核的计算机上编写程序(如果确实是导致问题的原因),并且确信该程序可以正常工作,只能启动它将其安装在另一台计算机上时出现死锁。请注意,不能因为你没或不容易看到死锁,这并不意味着此程序不会在 2 核机器上发生死锁。 该程序仍然有死锁倾向,只是很少发生——可以说是最糟糕的情况,因为问题不容易出现。
- 在 `DiningPhilosophers` 的构造方法中,每个哲学家都获得一个左右筷子的引用。除最后一个哲学家外,都是通过把哲学家放在下一双空闲筷子之间来初始化:
- - 最后一位哲学家得到了第0根筷子作为他的右筷子,所以圆桌就完成。
- - 那是因为最后一位哲学家正坐在第一个哲学家的旁边,而且他们俩都共用零筷子。[1]显示了以n为模数选择的右筷子,将最后一个哲学家绕到第一个哲学家的旁边。
+ - 最后一位哲学家得到了第 0 根筷子作为他的右筷子,所以圆桌就完成。
+ - 那是因为最后一位哲学家正坐在第一个哲学家的旁边,而且他们俩都共用零筷子。[1] 显示了以 n 为模数选择的右筷子,将最后一个哲学家绕到第一个哲学家的旁边。
- 现在,所有哲学家都可以尝试吃饭,每个哲学家都在旁边等待哲学家放下筷子。
- - 为了让每个哲学家在[3]上运行,调用 `runAsync()`,这意味着DiningPhilosophers的构造函数立即返回到[4]。
+ - 为了让每个哲学家在[3] 上运行,调用 `runAsync()`,这意味着 DiningPhilosophers 的构造函数立即返回到[4]。
- 如果没有任何东西阻止 `main()` 完成,程序就会退出,不会做太多事情。
- - `Nap` 对象阻止 `main()` 退出,然后在三秒后强制退出(假设/可能是)死锁程序。
+ - `Nap` 对象阻止 `main()` 退出,然后在三秒后强制退出 (假设/可能是) 死锁程序。
- 在给定的配置中,哲学家几乎不花时间思考。因此,他们在吃东西的时候都争着用筷子,而且往往很快就会陷入僵局。你可以改变这个:
-1. 通过增加[4]的值来添加更多哲学家。
+1. 通过增加[4] 的值来添加更多哲学家。
-2. 在Philosopher.java中取消注释行[1]。
+2. 在 Philosopher.java 中取消注释行[1]。
任一种方法都会减少死锁的可能性,这表明编写并发程序并认为它是安全的危险,因为它似乎“在我的机器上运行正常”。你可以轻松地说服自己该程序没有死锁,即使它不是。这个示例相当有趣,因为它演示了看起来可以正确运行,但实际上会可能发生死锁的程序。
@@ -2464,7 +2464,7 @@ public class DiningPhilosophers {
因为必须满足所有条件才能导致死锁,所以要阻止死锁的话,只需要破坏其中一个即可。在此程序中,防止死锁的一种简单方法是打破第四个条件。之所以会发生这种情况,是因为每个哲学家都尝试按照特定的顺序拾起自己的筷子:先右后左。因此,每个哲学家都有可能在等待左手的同时握住右手的筷子,从而导致循环等待状态。但是,如果其中一位哲学家尝试首先拿起左筷子,则该哲学家决不会阻止紧邻右方的哲学家拿起筷子,从而排除了循环等待。
-在**DiningPhilosophers.java**中,取消注释[1]和其后的一行。这将原来的哲学家[1]替换为筷子颠倒的哲学家。通过确保第二位哲学家拾起并在右手之前放下左筷子,我们消除了死锁的可能性。
+在 **DiningPhilosophers.java** 中,取消注释[1] 和其后的一行。这将原来的哲学家[1] 替换为筷子颠倒的哲学家。通过确保第二位哲学家拾起并在右手之前放下左筷子,我们消除了死锁的可能性。
这只是解决问题的一种方法。你也可以通过防止其他情况之一来解决它。
没有语言支持可以帮助防止死锁;你有责任通过精心设计来避免这种情况。对于试图调试死锁程序的人来说,这些都不是安慰。当然,避免并发问题的最简单,最好的方法是永远不要共享资源-不幸的是,这并不总是可能的。
@@ -2472,11 +2472,11 @@ public class DiningPhilosophers {
## 构造方法非线程安全
-当你在脑子里想象一个对象构造的过程,你会很容易认为这个过程是线程安全的。毕竟,在对象初始化完成前对外不可见,所以又怎会对此产生争议呢?确实,[Java 语言规范](https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.8.3) (JLS)自信满满地陈述道:“*没必要使构造器的线程同步,因为它会锁定正在构造的对象,直到构造器完成初始化后才对其他线程可见。*”
+当你在脑子里想象一个对象构造的过程,你会很容易认为这个过程是线程安全的。毕竟,在对象初始化完成前对外不可见,所以又怎会对此产生争议呢?确实,[Java 语言规范 ](https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.8.3) (JLS) 自信满满地陈述道:“*没必要使构造器的线程同步,因为它会锁定正在构造的对象,直到构造器完成初始化后才对其他线程可见。*”
不幸的是,对象的构造过程如其他操作一样,也会受到共享内存并发问题的影响,只是作用机制可能更微妙罢了。
-设想下使用一个 **static** 字段为每个对象自动创建唯一标识符的过程。为了测试其不同的实现过程,我们从一个接口开始。代码示例:
+设想下使用一个 **static** 字段为每个对象自动创建唯一标识符的过程。为了测试其不同的实现过程,我们从一个接口开始。代码示例:
```java
//concurrent/HasID.java
@@ -2485,7 +2485,7 @@ public interface HasID {
}
```
-然后 **StaticIDField** 类显式地实现该接口。代码示例:
+然后 **StaticIDField** 类显式地实现该接口。代码示例:
```java
// concurrent/StaticIDField.java
@@ -2541,11 +2541,11 @@ public class IDChecker {
}
```
-**MakeObjects** 类是一个生产者类,包含一个能够产生 List\ 类型的列表对象的 `get()` 方法。通过从每个 `HasID` 对象提取 `ID` 并放入列表中来生成这个列表对象,而 `test()` 方法则创建了两个并行的 **CompletableFuture** 对象,用于运行 **MakeObjects** 生产者类,然后获取运行结果。
+**MakeObjects** 类是一个生产者类,包含一个能够产生 List\ 类型的列表对象的 `get()` 方法。通过从每个 `HasID` 对象提取 `ID` 并放入列表中来生成这个列表对象,而 `test()` 方法则创建了两个并行的 **CompletableFuture** 对象,用于运行 **MakeObjects** 生产者类,然后获取运行结果。
使用 Guava 库中的 **Sets.`intersection()` 方法,计算出这两个返回的 List\ 对象中有多少相同的 `ID`(使用谷歌 Guava 库里的方法比使用官方的 `retainAll()` 方法速度快得多)。
-现在我们可以测试上面的 **StaticIDField** 类了。代码示例:
+现在我们可以测试上面的 **StaticIDField** 类了。代码示例:
```java
// concurrent/TestStaticIDField.java
@@ -2563,7 +2563,7 @@ public class TestStaticIDField {
13287
```
-结果中出现了很多重复项。很显然,纯静态 `int` 用于构造过程并不是线程安全的。让我们使用 **AtomicInteger** 来使其变为线程安全的。代码示例:
+结果中出现了很多重复项。很显然,纯静态 `int` 用于构造过程并不是线程安全的。让我们使用 **AtomicInteger** 来使其变为线程安全的。代码示例:
```java
// concurrent/GuardedIDField.java
@@ -2643,9 +2643,9 @@ public class SharedConstructorArgument{
0
```
-在这里,**SharedUser** 构造器实际上共享了相同的参数。即使 **SharedUser** 以完全无害且合理的方式使用其自己的参数,其构造器的调用方式也会引起冲突。**SharedUser** 甚至不知道它是以这种方式调用的,更不必说控制它了。
+在这里,**SharedUser** 构造器实际上共享了相同的参数。即使 **SharedUser** 以完全无害且合理的方式使用其自己的参数,其构造器的调用方式也会引起冲突。**SharedUser** 甚至不知道它是以这种方式调用的,更不必说控制它了。
-同步构造器并不被java语言所支持,但是通过使用同步语块来创建你自己的同步构造器是可能的(请参阅附录:[并发底层原理](./Appendix-Low-Level-Concurrency.md),来进一步了解同步关键字—— `synchronized`)。尽管JLS(java语言规范)这样陈述道:“……它会锁定正在构造的对象”,但这并不是真的——构造器实际上只是一个静态方法,因此同步构造器实际上会锁定该类的Class对象。我们可以通过创建自己的静态对象并锁定它,来达到与同步构造器相同的效果:
+同步构造器并不被 java 语言所支持,但是通过使用同步语块来创建你自己的同步构造器是可能的(请参阅附录:[并发底层原理 ](./Appendix-Low-Level-Concurrency.md),来进一步了解同步关键字—— `synchronized`)。尽管 JLS(java 语言规范)这样陈述道:“……它会锁定正在构造的对象”,但这并不是真的——构造器实际上只是一个静态方法,因此同步构造器实际上会锁定该类的 Class 对象。我们可以通过创建自己的静态对象并锁定它,来达到与同步构造器相同的效果:
```java
// concurrent/SynchronizedConstructor.java
@@ -2683,7 +2683,7 @@ public class SynchronizedConstructor{
0
```
-**Unsafe**类的共享使用现在就变得安全了。另一种方法是将构造器设为私有(因此可以防止继承),并提供一个静态Factory方法来生成新对象:
+**Unsafe** 类的共享使用现在就变得安全了。另一种方法是将构造器设为私有(因此可以防止继承),并提供一个静态 Factory 方法来生成新对象:
```java
// concurrent/SynchronizedFactory.java
@@ -2720,9 +2720,9 @@ public class SynchronizedFactory{
0
```
-通过同步静态工厂方法,可以在构造过程中锁定 **Class** 对象。
+通过同步静态工厂方法,可以在构造过程中锁定 **Class** 对象。
-这些示例充分表明了在并发Java程序中检测和管理共享状态有多困难。即使你采取“不共享任何内容”的策略,也很容易产生意外的共享事件。
+这些示例充分表明了在并发 Java 程序中检测和管理共享状态有多困难。即使你采取“不共享任何内容”的策略,也很容易产生意外的共享事件。
## 复杂性和代价
@@ -2808,7 +2808,7 @@ public class Pizza{
}
```
-这只算得上是一个平凡的状态机,就像**Machina**类一样。
+这只算得上是一个平凡的状态机,就像 **Machina** 类一样。
制作一个披萨,当披萨饼最终被放在盒子中时,就算完成最终任务了。 如果一个人在做一个披萨饼,那么所有步骤都是线性进行的,即一个接一个地进行:
@@ -2902,9 +2902,9 @@ Pizza 3:BOXED
1739
```
-现在,我们制作五个披萨的时间与制作单个披萨的时间就差不多了。 尝试删除标记为[1]的行后,你会发现它花费的时间是原来的五倍。 你还可以尝试将**QUANTITY**更改为4、8、10、16和17,看看会有什么不同,并猜猜看为什么会这样。
+现在,我们制作五个披萨的时间与制作单个披萨的时间就差不多了。 尝试删除标记为[1] 的行后,你会发现它花费的时间是原来的五倍。 你还可以尝试将 **QUANTITY** 更改为 4、8、10、16 和 17,看看会有什么不同,并猜猜看为什么会这样。
-**PizzaStreams** 类产生的每个并行流在它的`forEach()`内完成所有工作,如果我们将其各个步骤用映射的方式一步一步处理,情况会有所不同吗?
+**PizzaStreams** 类产生的每个并行流在它的`forEach()`内完成所有工作,如果我们将其各个步骤用映射的方式一步一步处理,情况会有所不同吗?
```java
// concurrent/PizzaParallelSteps.java
@@ -2982,7 +2982,7 @@ Pizza3: complete
答案是“否”,事后看来这并不奇怪,因为每个披萨都需要按顺序执行步骤。因此,没法通过分步执行操作来进一步提高速度,就像上文的 `PizzaParallelSteps.java` 里面展示的一样。
-我们可以使用 **CompletableFutures** 重写这个例子:
+我们可以使用 **CompletableFutures** 重写这个例子:
```java
// concurrent/CompletablePizza.java
@@ -3076,19 +3076,19 @@ Pizza4: complete
1797
```
-并行流和 **CompletableFutures** 是 Java 并发工具箱中最先进发达的技术。 你应该始终首先选择其中之一。 当一个问题很容易并行处理时,或者说,很容易把数据分解成相同的、易于处理的各个部分时,使用并行流方法处理最为合适(而如果你决定不借助它而由自己完成,你就必须撸起袖子,深入研究**Spliterator**的文档)。
+并行流和 **CompletableFutures** 是 Java 并发工具箱中最先进发达的技术。 你应该始终首先选择其中之一。 当一个问题很容易并行处理时,或者说,很容易把数据分解成相同的、易于处理的各个部分时,使用并行流方法处理最为合适(而如果你决定不借助它而由自己完成,你就必须撸起袖子,深入研究 **Spliterator** 的文档)。
-而当工作的各个部分内容各不相同时,使用 **CompletableFutures** 是最好的选择。比起面向数据,**CompletableFutures** 更像是面向任务的。
+而当工作的各个部分内容各不相同时,使用 **CompletableFutures** 是最好的选择。比起面向数据,**CompletableFutures** 更像是面向任务的。
对于披萨问题,结果似乎也没有什么不同。实际上,并行流方法看起来更简洁,仅出于这个原因,我认为并行流作为解决问题的首次尝试方法更具吸引力。
-由于制作披萨总需要一定的时间,无论你使用哪种并发方法,你能做到的最好情况,是在制作一个披萨的相同时间内制作n个披萨。 在这里当然很容易看出来,但是当你处理更复杂的问题时,你就可能忘记这一点。 通常,在项目开始时进行粗略的计算,就能很快弄清楚最大可能的并行吞吐量,这可以防止你因为采取无用的加快运行速度的举措而忙得团团转。
+由于制作披萨总需要一定的时间,无论你使用哪种并发方法,你能做到的最好情况,是在制作一个披萨的相同时间内制作 n 个披萨。 在这里当然很容易看出来,但是当你处理更复杂的问题时,你就可能忘记这一点。 通常,在项目开始时进行粗略的计算,就能很快弄清楚最大可能的并行吞吐量,这可以防止你因为采取无用的加快运行速度的举措而忙得团团转。
-使用 **CompletableFutures** 或许可以轻易地带来重大收益,但是在尝试更进一步时需要倍加小心,因为额外增加的成本和工作量会非常容易远远超出你之前拼命挤出的那一点点收益。
+使用 **CompletableFutures** 或许可以轻易地带来重大收益,但是在尝试更进一步时需要倍加小心,因为额外增加的成本和工作量会非常容易远远超出你之前拼命挤出的那一点点收益。
## 本章小结
-需要并发的唯一理由是“等待太多”。这也可以包括用户界面的响应速度,但是由于Java用于构建用户界面时并不高效,因此[^8]这仅仅意味着“你的程序运行速度还不够快”。
+需要并发的唯一理由是“等待太多”。这也可以包括用户界面的响应速度,但是由于 Java 用于构建用户界面时并不高效,因此[^8] 这仅仅意味着“你的程序运行速度还不够快”。
如果并发很容易,则没有理由拒绝并发。 正因为并发实际上很难,所以你应该仔细考虑是否值得为此付出努力,并考虑你能否以其他方式提升速度。
@@ -3104,7 +3104,7 @@ Pizza4: complete
1. 在线程等待共享资源时会降低速度。
-2. 线程管理产生额外CPU开销。
+2. 线程管理产生额外 CPU 开销。
3. 糟糕的设计决策带来无法弥补的复杂性。
@@ -3112,7 +3112,7 @@ Pizza4: complete
5. 跨平台的不一致。 通过一些示例,我发现了某些计算机上很快出现的竞争状况,而在其他计算机上却没有。 如果你在后者上开发程序,则在分发程序时可能会感到非常惊讶。
-另外,并发的应用是一门艺术。 Java旨在允许你创建尽可能多的所需要的对象来解决问题——至少在理论上是这样。[^9]但是,线程不是典型的对象:每个线程都有其自己的执行环境,包括堆栈和其他必要的元素,使其比普通对象大得多。 在大多数环境中,只能在内存用光之前创建数千个**Thread**对象。通常,你只需要几个线程即可解决问题,因此一般来说创建线程没有什么限制,但是对于某些设计而言,它会成为一种约束,可能迫使你使用完全不同的方案。
+另外,并发的应用是一门艺术。 Java 旨在允许你创建尽可能多的所需要的对象来解决问题——至少在理论上是这样。[^9] 但是,线程不是典型的对象:每个线程都有其自己的执行环境,包括堆栈和其他必要的元素,使其比普通对象大得多。 在大多数环境中,只能在内存用光之前创建数千个 **Thread** 对象。通常,你只需要几个线程即可解决问题,因此一般来说创建线程没有什么限制,但是对于某些设计而言,它会成为一种约束,可能迫使你使用完全不同的方案。
### 共享内存陷阱
@@ -3120,49 +3120,49 @@ Pizza4: complete
我花了多年的时间研究并发。 我了解到你永远无法相信使用共享内存并发的程序可以正常工作。 你可以轻易发现它是错误的,但永远无法证明它是正确的。 这是众所周知的并发原则之一。[^10]
-我遇到了许多人,他们对编写正确的线程程序的能力充满信心。 我偶尔开始认为我也可以做好。 对于一个特定的程序,我最初是在只有单个CPU的机器上编写的。 那时我能够说服自己该程序是正确的,因为我以为我对Java工具很了解。 而且在我的单CPU计算机上也没有失败。而到了具有多个CPU的计算机,程序出现问题不能运行后,我感到很惊讶,但这还只是众多问题中的一个而已。 这不是Java的错; “写一次,到处运行”,在单核与多核计算机间无法扩展到并发编程领域。这是并发编程的基本问题。 实际上你可以在单CPU机器上发现一些并发问题,但是在多线程实际上真的在并行运行的多CPU机器上,就会出现一些其他问题。
+我遇到了许多人,他们对编写正确的线程程序的能力充满信心。 我偶尔开始认为我也可以做好。 对于一个特定的程序,我最初是在只有单个 CPU 的机器上编写的。 那时我能够说服自己该程序是正确的,因为我以为我对 Java 工具很了解。 而且在我的单 CPU 计算机上也没有失败。而到了具有多个 CPU 的计算机,程序出现问题不能运行后,我感到很惊讶,但这还只是众多问题中的一个而已。 这不是 Java 的错; “写一次,到处运行”,在单核与多核计算机间无法扩展到并发编程领域。这是并发编程的基本问题。 实际上你可以在单 CPU 机器上发现一些并发问题,但是在多线程实际上真的在并行运行的多 CPU 机器上,就会出现一些其他问题。
再举一个例子,哲学家就餐的问题可以很容易地进行调整,因此几乎不会产生死锁,这会给你一种一切都棒极了的印象。当涉及到共享内存并发编程时,你永远不应该对自己的编程能力变得过于自信。
### This Albatross is Big
-如果你对Java并发感到不知所措,那说明你身处在一家出色的公司里。你可以访问**Thread**类的[Javadoc](https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html)页面, 看一下哪些方法现在是**Deprecated**(废弃的)。这些是Java语言设计者犯过错的地方,因为他们在设计语言时对并发性了解不足。
+如果你对 Java 并发感到不知所措,那说明你身处在一家出色的公司里。你可以访问 **Thread** 类的[Javadoc](https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html) 页面, 看一下哪些方法现在是 **Deprecated** (废弃的)。这些是 Java 语言设计者犯过错的地方,因为他们在设计语言时对并发性了解不足。
-事实证明,在Java的后续版本中添加的许多库解决方案都是无效的,甚至是无用的。 幸运的是,Java 8中的并行**Streams**和**CompletableFutures**都非常有价值。但是当你使用旧代码时,仍然会遇到旧的解决方案。
+事实证明,在 Java 的后续版本中添加的许多库解决方案都是无效的,甚至是无用的。 幸运的是,Java 8 中的并行 **Streams** 和 **CompletableFutures** 都非常有价值。但是当你使用旧代码时,仍然会遇到旧的解决方案。
-在本书的其他地方,我谈到了Java的一个基本问题:每个失败的实验都永远嵌入在语言或库中。 Java并发强调了这个问题。尽管有不少错误,但错误并不是那么多,因为有很多不同的尝试方法来解决问题。 好的方面是,这些尝试产生了更好,更简单的设计。 不利之处在于,在找到好的方法之前,你很容易迷失于旧的设计中。
+在本书的其他地方,我谈到了 Java 的一个基本问题:每个失败的实验都永远嵌入在语言或库中。 Java 并发强调了这个问题。尽管有不少错误,但错误并不是那么多,因为有很多不同的尝试方法来解决问题。 好的方面是,这些尝试产生了更好,更简单的设计。 不利之处在于,在找到好的方法之前,你很容易迷失于旧的设计中。
### 其他类库
-本章重点介绍了相对安全易用的并行工具流和**CompletableFutures**,并且仅涉及Java标准库中一些更细粒度的工具。 为避免你不知所措,我没有介绍你可能实际在实践中使用的某些库。我们使用了几个**Atomic**(原子)类,**ConcurrentLinkedDeque**,**ExecutorService**和**ArrayBlockingQueue**。附录:[并发底层原理](./Appendix-Low-Level-Concurrency.md)涵盖了其他一些内容,但是你还想探索**java.util.concurrent**的Javadocs。 但是要小心,因为某些库组件已被新的更好的组件所取代。
+本章重点介绍了相对安全易用的并行工具流和 **CompletableFutures** ,并且仅涉及 Java 标准库中一些更细粒度的工具。 为避免你不知所措,我没有介绍你可能实际在实践中使用的某些库。我们使用了几个 **Atomic** (原子)类,**ConcurrentLinkedDeque** ,**ExecutorService** 和 **ArrayBlockingQueue** 。附录:[并发底层原理 ](./Appendix-Low-Level-Concurrency.md) 涵盖了其他一些内容,但是你还想探索 **java.util.concurrent** 的 Javadocs。 但是要小心,因为某些库组件已被新的更好的组件所取代。
### 考虑为并发设计的语言
-通常,请谨慎地使用并发。 如果需要使用它,请尝试使用最现代的方法:并行流或**CompletableFutures**。 这些功能旨在(假设你不尝试共享内存)使你摆脱麻烦(在Java的世界范围内)。
+通常,请谨慎地使用并发。 如果需要使用它,请尝试使用最现代的方法:并行流或 **CompletableFutures** 。 这些功能旨在(假设你不尝试共享内存)使你摆脱麻烦(在 Java 的世界范围内)。
-如果你的并发问题变得比高级Java构造所支持的问题更大且更复杂,请考虑使用专为并发设计的语言,仅在需要并发的程序部分中使用这种语言是有可能的。 在撰写本文时,JVM上最纯粹的功能语言是Clojure(Lisp的一种版本)和Frege(Haskell的一种实现)。这些使你可以在其中编写应用程序的并发部分语言,并通过JVM轻松地与你的主要Java代码进行交互。 或者,你可以选择更复杂的方法,即通过外部功能接口(FFI)将JVM之外的语言与另一种为并发设计的语言进行通信。[^11]
+如果你的并发问题变得比高级 Java 构造所支持的问题更大且更复杂,请考虑使用专为并发设计的语言,仅在需要并发的程序部分中使用这种语言是有可能的。 在撰写本文时,JVM 上最纯粹的功能语言是 Clojure(Lisp 的一种版本)和 Frege(Haskell 的一种实现)。这些使你可以在其中编写应用程序的并发部分语言,并通过 JVM 轻松地与你的主要 Java 代码进行交互。 或者,你可以选择更复杂的方法,即通过外部功能接口(FFI)将 JVM 之外的语言与另一种为并发设计的语言进行通信。[^11]
-你很容易被一种语言绑定,迫使自己尝试使用该语言来做所有事情。 一个常见的示例是构建HTML / JavaScript用户界面。 这些工具确实很难使用,令人讨厌,并且有许多库允许你通过使用自己喜欢的语言编写代码来生成这些工具(例如,**Scala.js**允许你在Scala中完成代码)。
+你很容易被一种语言绑定,迫使自己尝试使用该语言来做所有事情。 一个常见的示例是构建 HTML / JavaScript 用户界面。 这些工具确实很难使用,令人讨厌,并且有许多库允许你通过使用自己喜欢的语言编写代码来生成这些工具(例如,**Scala.js** 允许你在 Scala 中完成代码)。
-心理上的便利是一个合理的考虑因素。 但是,我希望我在本章(以及附录:[并发底层原理](./Appendix-Low-Level-Concurrency.md))中已经表明Java并发是一个你可能无法逃离很深的洞。 与Java语言的任何其他部分相比,在视觉上检查代码同时记住所有陷阱所需要的的知识要困难得多。
+心理上的便利是一个合理的考虑因素。 但是,我希望我在本章(以及附录:[并发底层原理 ](./Appendix-Low-Level-Concurrency.md))中已经表明 Java 并发是一个你可能无法逃离很深的洞。 与 Java 语言的任何其他部分相比,在视觉上检查代码同时记住所有陷阱所需要的的知识要困难得多。
无论使用特定的语言、库使得并发看起来多么简单,都要将其视为一种妖术,因为总是有东西会在你最不期望出现的时候咬你。
### 拓展阅读
-《Java Concurrency in Practice》,出自Brian Goetz,Tim Peierls, Joshua Bloch,Joseph Bowbeer,David Holmes和 Doug Lea (Addison Wesley,2006年)——这些基本上就是Java并发世界中的名人名单了《Java Concurrency in Practice》第二版,出自 Doug Lea (Addison-Wesley,2000年)。尽管这本书出版时间远远早于Java 5发布,但Doug的大部分工作都写入了**java.util.concurrent**库。因此,这本书对于全面理解并发问题至关重要。 它超越了Java,讨论了跨语言和技术的并发编程。 尽管它在某些地方可能很钝,但值得多次重读(最好是在两个月之间进行消化)。 道格(Doug)是世界上为数不多的真正了解并发编程的人之一,因此这是值得的。
+《Java Concurrency in Practice》,出自 Brian Goetz,Tim Peierls, Joshua Bloch,Joseph Bowbeer,David Holmes 和 Doug Lea (Addison Wesley,2006 年)——这些基本上就是 Java 并发世界中的名人名单了《Java Concurrency in Practice》第二版,出自 Doug Lea (Addison-Wesley,2000 年)。尽管这本书出版时间远远早于 Java 5 发布,但 Doug 的大部分工作都写入了 **java.util.concurrent** 库。因此,这本书对于全面理解并发问题至关重要。 它超越了 Java,讨论了跨语言和技术的并发编程。 尽管它在某些地方可能很钝,但值得多次重读(最好是在两个月之间进行消化)。 道格(Doug)是世界上为数不多的真正了解并发编程的人之一,因此这是值得的。
-[^1]:例如,Eric-Raymond在“Unix编程艺术”(Addison-Wesley,2004)中提出了一个很好的案例。
+[^1]:例如,Eric-Raymond 在“Unix 编程艺术”(Addison-Wesley,2004)中提出了一个很好的案例。
[^2]:可以说,试图将并发性用于后续语言是一种注定要失败的方法,但你必须得出自己的结论
-[^3]:有人谈论在Java——10中围绕泛型做一些类似的基本改进,这将是非常令人难以置信的。
+[^3]:有人谈论在 Java——10 中围绕泛型做一些类似的基本改进,这将是非常令人难以置信的。
[^4]:这是一种有趣的,虽然不一致的方法。通常,我们期望在公共接口上使用显式类表示不同的行为
-[^5]:不,永远不会有纯粹的功能性Java。我们所能期望的最好的是一种在JVM上运行的全新语言。
+[^5]:不,永远不会有纯粹的功能性 Java。我们所能期望的最好的是一种在 JVM 上运行的全新语言。
[^6]:当两个任务能够更改其状态以使它们不会被阻止但它们从未取得任何有用的进展时,你也可以使用活动锁。
-[^7]: 而不是超线程;通常每个内核有两个超线程,并且在询问内核数量时,本书所使用的Java版本会报告超线程的数量。超线程产生了更快的上下文切换,但是只有实际的内核才真的工作,而不是超线程。 ↩
+[^7]: 而不是超线程;通常每个内核有两个超线程,并且在询问内核数量时,本书所使用的 Java 版本会报告超线程的数量。超线程产生了更快的上下文切换,但是只有实际的内核才真的工作,而不是超线程。 ↩
[^8]: 库就在那里用于调用,而语言本身就被设计用于此目的,但实际上它很少发生,以至于可以说”没有“。↩
-[^9]: 举例来说,如果没有Flyweight设计模式,在工程中创建数百万个对象用于有限元分析可能在Java中不可行。↩
+[^9]: 举例来说,如果没有 Flyweight 设计模式,在工程中创建数百万个对象用于有限元分析可能在 Java 中不可行。↩
[^10]: 在科学中,虽然从来没有一种理论被证实过,但是一种理论必须是可证伪的才有意义。而对于并发性,我们大部分时间甚至都无法得到这种可证伪性。↩
-[^11]: 尽管**Go**语言显示了FFI的前景,但在撰写本文时,它并未提供跨所有平台的解决方案。
+[^11]: 尽管 **Go** 语言显示了 FFI 的前景,但在撰写本文时,它并未提供跨所有平台的解决方案。
From 63a31fab8460c17ee0e299d75ebe8e7a6c24a999 Mon Sep 17 00:00:00 2001
From: arobot
Date: Thu, 17 Sep 2020 10:53:39 +0800
Subject: [PATCH 15/68] Update 24-Concurrent-Programming.md (#584)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
> ”the blocking never happens because the CompletableFuture is already complete, so the answer is instantly available.“
1. 笔误
2. answer这里应该是指结果
---
docs/book/24-Concurrent-Programming.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/book/24-Concurrent-Programming.md b/docs/book/24-Concurrent-Programming.md
index ab5d177a..052cd722 100755
--- a/docs/book/24-Concurrent-Programming.md
+++ b/docs/book/24-Concurrent-Programming.md
@@ -1439,7 +1439,7 @@ public class CompletedMachina {
**completedFuture()** 创建一个“已经完成”的 **CompletableFuture** 。对这样一个未来做的唯一有用的事情是 **get()** 里面的对象,所以这看起来似乎没有用。注意 **CompletableFuture** 被输入到它包含的对象。这个很重要。
-通常,**get()** 在等待结果时阻塞调用线程。此块可以通过 **InterruptedException** 或 **ExecutionException** 中断。在这种情况下,阻止永远不会发生,因为 CompletableFutureis 已经完成,所以答案立即可用。
+通常,**get()** 在等待结果时阻塞调用线程。此块可以通过 **InterruptedException** 或 **ExecutionException** 中断。在这种情况下,阻止永远不会发生,因为 **CompletableFuture** 已经完成,所以结果立即可用。
当我们将 **handle()** 包装在 **CompletableFuture** 中时,发现我们可以在 **CompletableFuture** 上添加操作来处理所包含的对象,使得事情变得更加有趣:
From c6a1207aa741d51e787c3447d2b80867a55235a7 Mon Sep 17 00:00:00 2001
From: Lane
Date: Thu, 17 Sep 2020 11:50:34 +0800
Subject: [PATCH 16/68] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BB=A3=E7=A0=81?=
=?UTF-8?q?=E5=88=86=E5=8F=B7=20&&=20=E9=87=8D=E6=96=B0=E7=94=9F=E6=88=90?=
=?UTF-8?q?=E7=9B=AE=E5=BD=95=E7=B4=A2=E5=BC=95=20(#586)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* add semicolon
* rebuild index
---
SUMMARY.md | 4 ++--
docs/book/18-Strings.md | 2 +-
docs/sidebar.md | 4 ++--
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/SUMMARY.md b/SUMMARY.md
index 5f2b8733..c7d1abb2 100644
--- a/SUMMARY.md
+++ b/SUMMARY.md
@@ -219,7 +219,7 @@
### [第十八章 字符串](book/18-Strings.md)
* [字符串的不可变](book/18-Strings.md#字符串的不可变)
- * [+ 的重载与 StringBuilder](book/18-Strings.md#+-的重载与-StringBuilder)
+ * [+ 的重载与 StringBuilder](book/18-Strings.md#-的重载与-StringBuilder)
* [意外递归](book/18-Strings.md#意外递归)
* [字符串操作](book/18-Strings.md#字符串操作)
* [格式化输出](book/18-Strings.md#格式化输出)
@@ -315,7 +315,7 @@
* [并行流](book/24-Concurrent-Programming.md#并行流)
* [创建和运行任务](book/24-Concurrent-Programming.md#创建和运行任务)
* [终止耗时任务](book/24-Concurrent-Programming.md#终止耗时任务)
- * [CompletableFuture类](book/24-Concurrent-Programming.md#CompletableFuture类)
+ * [CompletableFuture 类](book/24-Concurrent-Programming.md#CompletableFuture-类)
* [死锁](book/24-Concurrent-Programming.md#死锁)
* [构造方法非线程安全](book/24-Concurrent-Programming.md#构造方法非线程安全)
* [复杂性和代价](book/24-Concurrent-Programming.md#复杂性和代价)
diff --git a/docs/book/18-Strings.md b/docs/book/18-Strings.md
index 0b7bc7e5..151eed10 100755
--- a/docs/book/18-Strings.md
+++ b/docs/book/18-Strings.md
@@ -273,7 +273,7 @@ import java.util.stream.*;
public class InfiniteRecursion {
@Override
public String toString() {
- return " InfiniteRecursion address: " + this + "\n"
+ return " InfiniteRecursion address: " + this + "\n";
}
public static void main(String[] args) {
Stream.generate(InfiniteRecursion::new)
diff --git a/docs/sidebar.md b/docs/sidebar.md
index 5f2b8733..c7d1abb2 100644
--- a/docs/sidebar.md
+++ b/docs/sidebar.md
@@ -219,7 +219,7 @@
### [第十八章 字符串](book/18-Strings.md)
* [字符串的不可变](book/18-Strings.md#字符串的不可变)
- * [+ 的重载与 StringBuilder](book/18-Strings.md#+-的重载与-StringBuilder)
+ * [+ 的重载与 StringBuilder](book/18-Strings.md#-的重载与-StringBuilder)
* [意外递归](book/18-Strings.md#意外递归)
* [字符串操作](book/18-Strings.md#字符串操作)
* [格式化输出](book/18-Strings.md#格式化输出)
@@ -315,7 +315,7 @@
* [并行流](book/24-Concurrent-Programming.md#并行流)
* [创建和运行任务](book/24-Concurrent-Programming.md#创建和运行任务)
* [终止耗时任务](book/24-Concurrent-Programming.md#终止耗时任务)
- * [CompletableFuture类](book/24-Concurrent-Programming.md#CompletableFuture类)
+ * [CompletableFuture 类](book/24-Concurrent-Programming.md#CompletableFuture-类)
* [死锁](book/24-Concurrent-Programming.md#死锁)
* [构造方法非线程安全](book/24-Concurrent-Programming.md#构造方法非线程安全)
* [复杂性和代价](book/24-Concurrent-Programming.md#复杂性和代价)
From 46083fb5757f719bf968cc0a05863eb5b27b04f5 Mon Sep 17 00:00:00 2001
From: arobot
Date: Thu, 17 Sep 2020 15:59:29 +0800
Subject: [PATCH 17/68] Update 24-Concurrent-Programming.md (#585)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* Update 24-Concurrent-Programming.md
> And unless you know something specific about your system that changes things, you’ll probably want to use Async calls.
主谓宾 something specific changes things。作者应该是想说明逻辑中的一些具体实现可能会导致过程中的特定变化,如果使用异步实现会产生异常。而你是明白会产生这样的结果的,否则会更愿意使用异步调用。
原句中没有体现changes这个动作,读起来让人费解。
* Update 24-Concurrent-Programming.md
合并修改意见
---
docs/book/24-Concurrent-Programming.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/book/24-Concurrent-Programming.md b/docs/book/24-Concurrent-Programming.md
index 052cd722..668db583 100755
--- a/docs/book/24-Concurrent-Programming.md
+++ b/docs/book/24-Concurrent-Programming.md
@@ -1550,7 +1550,7 @@ Machina0: complete
这种“立即返回”的异步能力需要 `CompletableFuture` 库进行一些秘密(`client` 无感)工作。特别是,它将你需要的操作链存储为一组回调。当操作的第一个链路(后台操作)完成并返回时,第二个链路(后台操作)必须获取生成的 `Machina` 并开始工作,以此类推! 但这种异步机制没有我们可以通过程序调用栈控制的普通函数调用序列,它的调用链路顺序会丢失,因此它使用一个函数地址来存储的回调来解决这个问题。
-幸运的是,这就是你需要了解的有关回调的全部信息。程序员将这种人为制造的混乱称为 callback hell(回调地狱)。通过异步调用,`CompletableFuture` 帮你管理所有回调。 除非你知道系统的一些具体的变化,否则你更想使用异步调用来实现程序。
+幸运的是,这就是你需要了解的有关回调的全部信息。程序员将这种人为制造的混乱称为 callback hell(回调地狱)。通过异步调用,`CompletableFuture` 帮你管理所有回调。 除非你知道你系统中的一些特定逻辑会导致某些改变,或许你更想使用异步调用来实现程序。
- 其他操作
From cb4f1abd553f0b01dc55f7376395b6c334f292b1 Mon Sep 17 00:00:00 2001
From: Knn120 <19728079+Knn120@users.noreply.github.com>
Date: Thu, 17 Sep 2020 20:37:12 +0800
Subject: [PATCH 18/68] =?UTF-8?q?=E8=A7=A3=E5=86=B3=20issue#587=20?=
=?UTF-8?q?=E6=9C=89=E4=B8=A4=E4=B8=AA=E7=AB=A0=E8=8A=82=E7=BC=BA=E5=B0=91?=
=?UTF-8?q?=E5=8A=A0=E6=B3=A8=E9=97=AE=E9=A2=98=20(#588)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* Update 20-Generics.md
* Update Appendix-Understanding-equals-and-hashCode.md
增加脚注
---
docs/book/20-Generics.md | 6 +++---
docs/book/Appendix-Understanding-equals-and-hashCode.md | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/docs/book/20-Generics.md b/docs/book/20-Generics.md
index 00d25272..43bb33ba 100644
--- a/docs/book/20-Generics.md
+++ b/docs/book/20-Generics.md
@@ -4298,7 +4298,7 @@ test string 2 1494331663027 2
*/
```
-**Mixin** 类基本上是在使用*委托*,因此每个混入类型都要求在 **Mixin** 中有一个相应的域,而你必须在 **Mixin** 中编写所有必需的方法,将方法调用转发给恰当的对象。这个示例使用了非常简单的类,但是当使用更复杂的混型时,代码数量会急速增加。
+**Mixin** 类基本上是在使用*委托*,因此每个混入类型都要求在 **Mixin** 中有一个相应的域,而你必须在 **Mixin** 中编写所有必需的方法,将方法调用转发给恰当的对象。这个示例使用了非常简单的类,但是当使用更复杂的混型时,代码数量会急速增加。[^4]
### 使用装饰器模式
@@ -4539,7 +4539,7 @@ Clank!
```
在 Python 和 C++ 中,**Dog** 和 **Robot** 没有任何共同的东西,只是碰巧有两个方法具有相同的签名。从类型的观点看,它们是完全不同的类型。但是,`perform()` 不关心其参数的具体类型,并且潜在类型机制允许它接受这两种类型的对象。
-C++ 确保了它实际上可以发送的那些消息,如果试图传递错误类型,编译器就会给你一个错误消息(这些错误消息从历史上看是相当可怕和冗长的,是 C++ 的模版名声欠佳的主要原因)。尽管它们是在不同时期实现这一点的,C++ 在编译期,而 Python 在运行时,但是这两种语言都可以确保类型不会被误用,因此被认为是强类型的。潜在类型机制没有损害强类型机制。
+C++ 确保了它实际上可以发送的那些消息,如果试图传递错误类型,编译器就会给你一个错误消息(这些错误消息从历史上看是相当可怕和冗长的,是 C++ 的模版名声欠佳的主要原因)。尽管它们是在不同时期实现这一点的,C++ 在编译期,而 Python 在运行时,但是这两种语言都可以确保类型不会被误用,因此被认为是强类型的。[^5]潜在类型机制没有损害强类型机制。
### Go 中的潜在类型
@@ -5064,7 +5064,7 @@ public class Suppliers {
}
```
-`create()` 为你创建一个新的 **Collection** 子类型,而 `fill()` 的第一个版本将元素放入 **Collection** 的现有子类型中。 请注意,还会返回传入的容器的确切类型,因此不会丢失类型信息。
+`create()` 为你创建一个新的 **Collection** 子类型,而 `fill()` 的第一个版本将元素放入 **Collection** 的现有子类型中。 请注意,还会返回传入的容器的确切类型,因此不会丢失类型信息。[^6]
前两种方法一般都受约束,只能与 **Collection** 子类型一起使用。`fill()` 的第二个版本适用于任何类型的 **holder** 。 它需要一个附加参数:未绑定方法引用 `adder. fill()` ,使用辅助潜在类型来使其与任何具有添加元素方法的 **holder** 类型一起使用。因为此未绑定方法 **adder** 必须带有一个参数(要添加到 **holder** 的元素),所以 **adder** 必须是 `BiConsumer ` ,其中 **H** 是要绑定到的 **holder** 对象的类型,而 **A** 是要被添加的绑定元素类型。 对 `accept()` 的调用将使用参数 a 调用对象 **holder** 上的未绑定方法 **holder**。
diff --git a/docs/book/Appendix-Understanding-equals-and-hashCode.md b/docs/book/Appendix-Understanding-equals-and-hashCode.md
index 01889642..a5c3dc25 100644
--- a/docs/book/Appendix-Understanding-equals-and-hashCode.md
+++ b/docs/book/Appendix-Understanding-equals-and-hashCode.md
@@ -675,7 +675,7 @@ SlowMap.java 说明了创建一种新的Map并不困难。但是正如它的名
答案就是:数组并不保存键本身。而是通过键对象生成一个数字,将其作为数组的下标。这个数字就是散列码,由定义在Object中的、且可能由你的类覆盖的hashCode()方法(在计算机科学的术语中称为散列函数)生成。
-于是查询一个值的过程首先就是计算散列码,然后使用散列码查询数组。如果能够保证没有冲突(如果值的数量是固定的,那么就有可能),那可就有了一个完美的散列函数,但是这种情况只是特例。。通常,冲突由外部链接处理:数组并不直接保存值,而是保存值的 list。然后对 list中的值使用equals()方法进行线性的查询。这部分的查询自然会比较慢,但是,如果散列函数好的话,数组的每个位置就只有较少的值。因此,不是查询整个list,而是快速地跳到数组的某个位置,只对很少的元素进行比较。这便是HashMap会如此快的原因。
+于是查询一个值的过程首先就是计算散列码,然后使用散列码查询数组。如果能够保证没有冲突(如果值的数量是固定的,那么就有可能),那可就有了一个完美的散列函数,但是这种情况只是特例。[^1]。通常,冲突由外部链接处理:数组并不直接保存值,而是保存值的 list。然后对 list中的值使用equals()方法进行线性的查询。这部分的查询自然会比较慢,但是,如果散列函数好的话,数组的每个位置就只有较少的值。因此,不是查询整个list,而是快速地跳到数组的某个位置,只对很少的元素进行比较。这便是HashMap会如此快的原因。
理解了散列的原理,我们就能够实现一个简单的散列Map了:
From 68fc4fdf1d7b085878353aea0e180c082ecf4735 Mon Sep 17 00:00:00 2001
From: rainbow
Date: Mon, 21 Sep 2020 10:53:02 +0800
Subject: [PATCH 19/68] =?UTF-8?q?=E4=BF=AE=E5=A4=8D25=E7=AB=A0-=E6=A8=A1?=
=?UTF-8?q?=E6=9D=BF=E6=96=B9=E6=B3=95=E6=A8=A1=E5=BC=8F=E4=B8=AD=E7=9A=84?=
=?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=A0=BC=E5=BC=8F=E9=97=AE=E9=A2=98=20(#590)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* 修改25章-模板方法模式中的代码格式问题
* fix more code format error
---
docs/book/25-Patterns.md | 58 +++++++++++++++++++++++++++++++---------
1 file changed, 45 insertions(+), 13 deletions(-)
diff --git a/docs/book/25-Patterns.md b/docs/book/25-Patterns.md
index f3d37647..43c4f929 100644
--- a/docs/book/25-Patterns.md
+++ b/docs/book/25-Patterns.md
@@ -122,8 +122,26 @@ abstract class ApplicationFramework {
abstract void customize1();
- abstract void customize2(); // "private" means automatically "final": private void templateMethod() { IntStream.range(0, 5).forEach( n -> { customize1(); customize2(); }); }}// Create a new "application": class MyApp extends ApplicationFramework { @Override void customize1() { System.out.print("Hello "); }@Override
+ abstract void customize2();
+
+ // "private" means automatically "final":
+ private void templateMethod() {
+ IntStream.range(0, 5).forEach(
+ n -> {
+ customize1();
+ customize2();
+ });
+ }
+}
+// Create a new "application":
+class MyApp extends ApplicationFramework {
+ @Override
+ void customize1() {
+ System.out.print("Hello ");
+ }
+
+ @Override
void customize2() {
System.out.println("World!");
}
@@ -134,8 +152,7 @@ public class TemplateMethod {
new MyApp();
}
}
-/*
-Output:
+/* Output:
Hello World!
Hello World!
Hello World!
@@ -245,8 +262,20 @@ class State implements StateBase {
@Override
public void changeImp(StateBase newImp) {
implementation = newImp;
- }// Pass method calls to the implementation: @Override public void f() { implementation.f(); } @Override public void g() { implementation.g(); } @Override
+ }
+ // Pass method calls to the implementation:
+ @Override
+ public void f() {
+ implementation.f();
+ }
+
+ @Override
+ public void g() {
+ implementation.g();
+ }
+
+ @Override
public void h() {
implementation.h();
}
@@ -302,7 +331,8 @@ public class StateDemo {
}
public static void main(String[] args) {
- StateBase b = new State(new Implementation1());
+ StateBase b =
+ new State(new Implementation1());
test(b);
b.changeImp(new Implementation2());
test(b);
@@ -349,9 +379,6 @@ interface State {
abstract class StateMachine {
protected State currentState;
- Nap(0.5);
-System.out.println("Washing"); new
-
protected abstract boolean changeState();
// Template method:
@@ -362,9 +389,12 @@ System.out.println("Washing"); new
}
// A different subclass for each state:
+
class Wash implements State {
@Override
public void run() {
+ System.out.println("Washing");
+ new Nap(0.5);
}
}
@@ -386,9 +416,11 @@ class Rinse implements State {
class Washer extends StateMachine {
private int i = 0;
-
// The state table:
- private State[] states = {new Wash(), new Spin(), new Rinse(), new Spin(),};
+ private State[] states = {
+ new Wash(), new Spin(),
+ new Rinse(), new Spin(),
+ };
Washer() {
runAll();
@@ -401,7 +433,8 @@ class Washer extends StateMachine {
// surrogate reference to a new object:
currentState = states[i++];
return true;
- } else return false;
+ } else
+ return false;
}
}
@@ -410,8 +443,7 @@ public class StateMachineDemo {
new Washer();
}
}
-/*
-Output:
+/* Output:
Washing
Spinning
Rinsing
From 4cfa753144315083ecbf22074cbc35da256eb6c2 Mon Sep 17 00:00:00 2001
From: PEGASUS <32333727+PEGASUS1993@users.noreply.github.com>
Date: Wed, 23 Sep 2020 16:08:06 +0800
Subject: [PATCH 20/68] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E4=B8=80=E4=BA=9B?=
=?UTF-8?q?=E5=B0=8F=E5=B0=8F=E5=B0=8F=E5=B0=8F=E6=AD=A7=E4=B9=89=20(#593)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* Update 00-Preface.md
* Update 00-On-Java-8.md
* Update 00-Preface.md
* Update 00-Preface.md
* Update Appendix-Becoming-a-Programmer.md
---
docs/book/Appendix-Becoming-a-Programmer.md | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/docs/book/Appendix-Becoming-a-Programmer.md b/docs/book/Appendix-Becoming-a-Programmer.md
index edbf4c8b..437fbcc3 100644
--- a/docs/book/Appendix-Becoming-a-Programmer.md
+++ b/docs/book/Appendix-Becoming-a-Programmer.md
@@ -12,25 +12,25 @@
我的朋友丹尼尔(就是设计我的书封面的人)有一个兄弟,他有段时间通过向酒吧和餐馆提供弹球机来赚钱。他有一台投币式街机(老虎机),最早的《乓》游戏之一,我对此全然不知,到现在我还忍受不了这东西(现在我几乎不玩电脑游戏,这样看来我可能是个没有幽默的人,但似乎编程比玩电脑游戏更有趣、更具挑战性。)
-后来我在高中参与了摄影和新闻工作,在大学的第一年就主修新闻学。我觉得自己已经从学校学到了足够多的东西,又转修了物理学。后来我在加州大学欧文分校完成了物理学位,如果我当时选择了一个特定的工程领域,修了足够的工程课就能拿到双专业,但我试图走得更远一些,所以最后我获得的本科学位是 "应用物理"。作为一名本科生,我多多少少学习了一些可以自娱自乐,但又没有任何深度的计算机编程课程。我个人认为在这些课程细细熏陶下,帮我打下了一定的基础,但事实我理解的这些东西没有任何深度。我不知道计算机、编译器或解释器有什么区别(只是对编译器和解释器一点点的理解)。对我来说计算机是绝对可靠的,而且我从来没有想过在程序语言和操作系统中会有出现错误的可能。
+后来我在高中参与了摄影和新闻工作,在大学的第一年就主修新闻学。我觉得自己已经从学校学到了足够多的东西,又转修了物理学。后来我在加州大学尔湾分校完成了物理学位,如果我当时选择了一个特定的工程领域,修了足够的工程课就能拿到双专业,但我试图走得更远一些,所以最后我获得的本科学位是 "应用物理"。作为一名本科生,我多多少少学习了一些可以自娱自乐,但又没有任何深度的计算机编程课程。我个人认为在这些课程细细熏陶下,帮我打下了一定的基础,但事实我理解的这些东西没有任何深度。我不知道计算机、编译器或解释器有什么区别(只是对编译器和解释器一点点的理解)。对我来说计算机是绝对可靠的,而且我从来没有想过在程序语言和操作系统中会有出现错误的可能。
-后来我去了在加州州立理工大学攻读研究生,主要有三点原因
+后来我去了加州州立理工大学攻读研究生,主要有三点原因:
-1. 我真的非常喜欢物理学这个领域
+1. 我真的非常喜欢物理学这个领域;
-2. 他们接受了我,甚至给了我一份教学工作和奖学金
+2. 他们接收了我,甚至给了我一份教学工作和奖学金 ;
-3. 出乎意料的是他们给我的工作时间不止一个夏天
+3. 出乎意料的是他们给我的工作时间不止一个夏天。
而我完全没做好上班的准备。
-作为一名物理专业的学生,我学习的是太阳能发电系统,当时太阳能发电系统很大 (如果你的房子上装了太阳能或生意上是关于太阳能系统,加州就会给予税收抵免,因此也兴起很多生意),加州理工大学也承诺会在工程系开设相应的课程。然而因为学校没有提供必要的课程,要想获得在太阳能工程的学位得花好几年时间。所以我学习了研究生其他的工程课,包括介绍机械,太阳能,电气和电子工程。我上的课是非电气工程专业的电气工程导论。最常见的研究生工程课程是计算机工程专业,所以最后我拿了那个学位。我还上了艺术课,几门舞蹈课,还有一些计算机科学课程 (Pascal和数据结构),在计算机工程中,我终于弄清楚了处理器的工作流程,从那以后我一直带着一个处理器在身上。这些就是我学的计算机基础知识。
+作为一名物理专业的学生,我学习的是太阳能发电系统,当时太阳能发电系统很大 (如果你的房子上装了太阳能或生意上是关于太阳能系统,加州就会给予税收抵免,因此也兴起很多生意),加州州立理工大学也承诺会在工程系开设相应的课程。然而因为学校没有提供必要的课程,要想获得在太阳能工程的学位得花好几年时间。所以我学习了研究生其他的工程课,包括介绍机械,太阳能,电气和电子工程。我上的课是非电气工程专业的电气工程导论。最常见的研究生工程课程是计算机工程专业,所以最后我拿了那个学位。我还上了艺术课,几门舞蹈课,还有一些计算机科学课程 (Pascal和数据结构),在计算机工程中,我终于弄清楚了处理器的工作流程,从那以后我一直带着一个处理器在身上。这些就是我学的计算机基础知识。
刚开始工作的时候,凭借着一堆硬件和相对简单低水平的编程,做了一名计算机工程师。因为C语言似乎是理想的嵌入式系统语言,于是我开始自学,并慢慢开始了解更多关于编程语言的东西。我们在这家公司从源代码构建编译器,这让我大开眼界。 (想象一下一个编译器只是另一个软件的一部分!)
当我去华盛顿大学海洋学院为Tom Keffer后来创建了“疯狗浪”)工作时,我们决定使用C++。我只有一本Stroustrup写的非初学者书可以参考,最终不得不通过检查C++预处理器生成的中间C代码来了解语言的功能。这个过程非常痛苦,但学习的效果很好。从那以后我就用相同的方式学习,因为它让我学习了如何剖析一种语言,并看到它本质的能力,与此同时开始有了批判性思维。
-我并没有理解清楚所有的概念。只是在之后的日子里不断反复,我所知道的一切需要时间才能消化吸收。如果我现在能很容易地理解一个新概念,那只是因为它是我已经知道的积累概念的一个变种。在加州理工大学招收非计算机本科学历的计算机科学研究生项目中,学生们曾经说他们花了一年的时间才弄清楚他们对计算机的困惑(他们正在沉浸程序之中)。当人们学习计算机时,他们往往会对自己抱有不切实际的期望,通常是他们听说学计算机编程的好处,就希望在几周内找到一份高薪的工作。但是,最好的学习过程是先对计算机感兴趣,随着时间的推移,学习的越来越多,自然的就开始自学。
+我并没有理解清楚所有的概念。只是在之后的日子里不断反复,我所知道的一切需要时间才能消化吸收。如果我现在能很容易地理解一个新概念,那只是因为它是我已经知道的积累概念的一个变种。在加州州立理工大学招收非计算机本科学历的计算机科学研究生项目中,学生们曾经说他们花了一年的时间才弄清楚他们对计算机的困惑(他们正在沉浸程序之中)。当人们学习计算机时,他们往往会对自己抱有不切实际的期望,通常是他们听说学计算机编程的好处,就希望在几周内找到一份高薪的工作。但是,最好的学习过程是先对计算机感兴趣,随着时间的推移,学习的越来越多,自然的就开始自学。
这些就是我主要做的事,尽管我通过学计算机工程有还算扎实的基础,但我没上过编程课,而是通过自学。在此期间我也在不断地学习新事物,在这个行业里,不断学习是非常重要的一部分。
From d0076930a80ecfe13998f61f7dc37d113bd56c95 Mon Sep 17 00:00:00 2001
From: PolygonT <56947591+PolygonT@users.noreply.github.com>
Date: Wed, 23 Sep 2020 03:08:43 -0500
Subject: [PATCH 21/68] Update 24-Concurrent-Programming.md (#592)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
final和int间添加空格
From 6eab4fb16d9ae542ef90bd1da819316a553dfb69 Mon Sep 17 00:00:00 2001
From: TENCHIANG
Date: Fri, 25 Sep 2020 14:16:34 +0800
Subject: [PATCH 22/68] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=BF=BB=E8=AF=91?=
=?UTF-8?q?=EF=BC=9A24-Concurrent-Programming.md#=E5=B9=B6=E5=8F=91?=
=?UTF-8?q?=E7=9A=84=E8=B6=85=E8=83=BD=E5=8A=9B=20(#594)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* 优化翻译:24-Concurrent-Programming.md#并发的超能力
* 优化翻译:24-Concurrent-Programming.md#并发的超能力 fix翻译错误
---
docs/book/24-Concurrent-Programming.md | 37 +++++++++++++-------------
1 file changed, 19 insertions(+), 18 deletions(-)
diff --git a/docs/book/24-Concurrent-Programming.md b/docs/book/24-Concurrent-Programming.md
index 668db583..f0eaa0d2 100755
--- a/docs/book/24-Concurrent-Programming.md
+++ b/docs/book/24-Concurrent-Programming.md
@@ -1,6 +1,7 @@
[TOC]
+
# 第二十四章 并发编程
> 爱丽丝:“我可不想到疯子中间去”
@@ -89,47 +90,47 @@ slowdown occurs):
## 并发的超能力
-想象一下,你置身于一部科幻电影。你必须在高层建筑中搜索一个精心巧妙地隐藏在建筑物的一千万个房间之一中的单个物品。你进入建筑物并沿着走廊向下移动。走廊分开了。
+想象一下,你置身于一部科幻电影。你必须在一栋大楼中找到一个东西,它被小心而巧妙地隐藏在大楼一千万个房间中的一间。你进入大楼,沿着走廊走下去。走廊是分开的。
-你自己完成这项任务需要一百个生命周期。
+一个人完成这项任务要花上一百辈子的时间。
现在假设你有一个奇怪的超能力。你可以将自己一分为二,然后在继续前进的同时将另一半送到另一个走廊。每当你在走廊或楼梯上遇到分隔到下一层时,你都会重复这个分裂的技巧。最终,整个建筑中的每个走廊的终点都有一个你。
-每个走廊都有一千个房间。你的超能力变得有点弱,所以你只能分裂出 50 个自己来搜索这间房间。
+每个走廊都有一千个房间。此时你的超能力变得弱了一点,你只能克隆 50 个自己来并发搜索走廊里面的房间。
-一旦克隆体进入房间,它必须搜索房间的每个角落。这时它切换到了第二种超能力。它分裂成了一百万个纳米机器人,每个机器人都会飞到或爬到房间里一些看不见的地方。你不需要了解这种功能 - 一旦你开启它就会自动工作。在他们自己的控制下,纳米机器人开始行动,搜索房间然后回来重新组装成你,突然间,你获得了寻找的物品是否在房间内的消息。
+一旦克隆体进入房间,它必须搜索房间的每个角落。这时它切换到了第二种超能力。它分裂成了一百万个纳米机器人,每个机器人都会飞到或爬到房间里一些看不见的地方。你不需要了解这种功能 - 一旦你开启它就会自动工作。在他们自己的控制下,纳米机器人开始行动,搜索房间然后回来重新组装成你,突然间,不知怎么的,你就知道这间房间里有没有那个东西。
我很想说,“并发就是刚才描述的置身于科幻电影中的超能力“就像你自己可以一分为二然后解决更多的问题一样简单。但是问题在于,我们来描述这种现象的任何模型最终都是泄漏抽象的(leaky abstraction)。
-以下是其中一个漏洞:在理想的世界中,每次克隆自己时,你还会复制硬件处理器来运行该克隆。但当然不会发生这种情况 - 你的机器上可能有四个或八个处理器(通常在写入时)。你可能还有更多,并且仍有许多情况只有一个处理器。在抽象的讨论中,物理处理器的分配方式不仅可以泄漏,甚至可以支配你的决策
+以下是其中一个漏洞:在理想的世界中,每次克隆自己时,还需要复制一个物理处理器来运行该克隆。这当然是不现实的——实际上,你的机器上一般只有 4 个或 8 个处理器核心(编写本文时的典型情况)。你也可能更多,但仍有很多情况下只有一个单核处理器。在关于抽象的讨论中,分配物理处理器核心这本身就是抽象的泄露,甚至也可以支配你的决策。
-让我们在科幻电影中改变一些东西。现在当每个克隆搜索者最终到达一扇门时,他们必须敲门并等到有人回答。如果我们每个搜索者有一个处理器,这没有问题 - 处理器只是空闲,直到门被回答。但是如果我们只有 8 个处理器和数千个搜索者,我们不希望处理器仅仅因为某个搜索者恰好在等待回答中被锁住而闲置下来。相反,我们希望将处理器应用于可以真正执行工作的搜索者身上,因此需要将处理器从一个任务切换到另一个任务的机制。
+让我们在科幻电影中改变一些东西。现在当每个克隆搜索者最终到达一扇门时,他们必须敲门并等到有人开门。如果每个搜索者都有一个处理器核心,这没有问题——只是空闲等待直到有人开门。但是如果我们只有 8 个处理器核心却有几千个搜索者,我们不希望处理器仅仅因为某个搜索者恰好在等待回答中被锁住而闲置下来。相反,我们希望将处理器应用于可以真正执行工作的搜索者身上,因此需要将处理器从一个任务切换到另一个任务的机制。
-许多模型能够有效地隐藏处理器的数量,并允许你假装你的数量非常大。但是有些情况会发生故障的时候,你必须知道处理器的数量,以便你可以解决这个问题。
+许多模型能够有效地隐藏处理器的数量,允许你假装有很多个处理器。但在某些情况下,这种方法会失效,这时你必须知道处理器核心的真实数量,以便处理这个问题。
-其中一个最大的影响取决于你是单个处理器还是多个处理器。如果你只有一个处理器,那么任务切换的成本也由该处理器承担,将并发技术应用于你的系统会使它运行得更慢。
+最大的影响之一取决于您是使用单核处理器还是多核处理器。如果你只有单核处理器,那么任务切换的成本也由该核心承担,将并发技术应用于你的系统会使它运行得更慢。
-这可能会让你认为,在单个处理器的情况下,编写并发代码时没有意义。然而,有些情况下,并发模型会产生更简单的代码,实际上为了这个目的值得让它运行得更慢。
+这可能会让你以为,在单核处理器的情况下,编写并发代码是没有意义的。然而,有些情况下,并发模型会产生更简单的代码,光是为了这个目的就值得舍弃一些性能。
-在克隆体敲门等待的情况下,即使单处理器系统也能从并发中受益,因为它可以从等待(阻塞)的任务切换到准备好的任务。但是如果所有任务都可以一直运行那么切换的成本反而会使任务变慢,在这种情况下,如果你有多个进程,并发通常只会有意义。
+在克隆体敲门等待的情况下,即使单核处理器系统也能从并发中受益,因为它可以从等待(阻塞)的任务切换到准备运行的任务。但是如果所有任务都可以一直运行那么切换的成本反而会使任务变慢,在这种情况下,如果你有多个进程,并发通常只会有意义。
-假设你正在尝试破解某种密码,在同一时间内参与破解的线程越多,你越快得到答案的可能性就越大。每个线程都能持续使用你所分配的处理器时间,在这种情况下(一个计算约束问题),你的代码中分配的线程数应该和你拥有的处理器的数量保持一致。
+如果你正在尝试破解某种密码,在同一时间内参与破解的线程越多,你越快得到答案的可能性就越大。每个线程都能持续使用你所分配的处理器时间,在这种情况下(CPU 密集型问题),你代码中的线程数应该和你拥有的处理器的核心数保持一致。
-在接听电话的客户服务部门,你只有一定数量的员工,但是你的部门可能会收到很多电话。这些员工(处理器)一次只能处理一个电话,直到完成,与此同时,额外的电话必须排队。
+在接听电话的客户服务部门,你只有一定数量的员工,但是你的部门可能会打来很多电话。这些员工(处理器)一次只能接听一个电话直到打完,此时其它打来的电话必须排队等待。
-在“鞋匠和精灵”的童话故事中,鞋匠有很多工作要做,当他睡着时,出现了一群精灵来为他制作鞋子。这里的工作是分布式的,但即使使用大量的物理处理器,在制造鞋子的某些部件时也会产生限制 - 例如,鞋底需要大量的时间去制作,这会限制制鞋的速度并改变你设计解决方案的方式。
+在“鞋匠和精灵”的童话故事中,鞋匠有很多工作要做,当他睡着时,出现了一群精灵来为他制作鞋子。这里的工作是分布式的,但即使使用大量的物理处理器,在制造鞋子的某些部件时也会产生限制——例如,如果鞋底的制作时间最长,这就限制了鞋子的制作速度,这也会改变你设计解决方案的方式。
-因此,你尝试解决的问题驱动解决方案的设计。有一个迷人的抽象那就是将一个问题分解为子问题并且让它们独立运行,然后就是赤裸裸的现实。物理现实一次又一次地打了这种抽象的脸。
+因此,你要解决的问题推动了解决方案的设计。将一个问题分解成“独立运行”的子任务,这是一种美好的抽象,然后就是残酷的现实:物理现实不断地侵入和动摇这个抽象。
-这只是问题的一部分。考虑一个制作蛋糕的工厂。我们不知何故在工人中分发了蛋糕制作任务,但是现在是时候让工人把蛋糕放在盒子里了。那里有一个盒子,准备存放蛋糕。但是,在工人将蛋糕放入盒子之前,另一名工人投入并将蛋糕放入盒子中!我们的工人已经把蛋糕放进去了,然后就开始了!这两个蛋糕被砸碎并毁了。这是常见的“共享内存”问题,产生我们称之为竞争条件的问题,其结果取决于哪个工作人员可以首先将蛋糕放入盒子中(通常使用锁机制来解决问题,因此一个工作人员可以先拿到盒子并防止蛋糕被砸烂)。
+这只是问题的一部分:考虑一个制作蛋糕的工厂。我们以某种方式把制作蛋糕的任务分给了工人们,但是现在是时候让工人把蛋糕放在盒子里了。那里有一个盒子,准备存放蛋糕。但是在工人把蛋糕放进盒子之前,另一个工人就冲过去,把蛋糕放进盒子里,砰!这两个蛋糕撞到一起砸坏了。这是常见的“共享内存”问题,会产生所谓的竞态条件(race condition),其结果取决于哪个工人能先把蛋糕放进盒子里(通常使用锁机制来解决问题,因此一个工作人员可以先抓住一个盒子并防止蛋糕被砸烂)。
-当“同时”执行的任务相互干扰时,会出现问题。它可以以如此微妙和偶然的方式发生,可能公平地说,并发性“可以说是确定性的,但实际上是非确定性的。”也就是说,你可以假设编写通过维护和代码检查正常工作的并发程序。然而,在实践中,我们编写的并发程序似乎都能正常工作,但是在适当的条件下,将会失败。这些情况可能永远不会发生,或者在你在测试期间几乎很难发现它们。实际上,编写测试代码通常无法为并发程序生成故障条件。由此产生的失败只会偶尔发生,因此它们以客户投诉的形式出现。
-这是学习并发中最强有力的论点之一:如果你忽略它,你可能会受伤。
+当“同时”执行的任务相互干扰时,就会出现问题。这可能以一种微妙而偶然的方式发生,因此可以说并发是“可以论证的确定性,但实际上是不确定性的”。也就是说,假设你很小心地编写并发程序,而且通过了代码检查可以正确运行。然而实际上,我们编写的并发程序大部分情况下都能正常运行,但是在一些情况下会失败。这些情况可能永远不会发生,或者在你在测试期间几乎很难发现它们。实际上,编写测试代码通常无法为并发程序生成故障条件。由此产生的失败只会偶尔发生,因此它们以客户投诉的形式出现。这是学习并发中最强有力的论点之一:如果你忽略它,你可能会受伤。
-因此,并发似乎充满了危险,如果这让你有点害怕,这可能是一件好事。尽管 Java 8 在并发性方面做出了很大改进,但仍然没有像编译时验证 (compile-time verification) 或受检查的异常 (checked exceptions) 那样的安全网来告诉你何时出现错误。通过并发,你只能依靠自己,只有知识渊博,保持怀疑和积极进取的人,才能用 Java 编写可靠的并发代码。
+因此,并发似乎充满了危险,如果这让你有点害怕,这可能是一件好事。尽管 Java 8 在并发性方面做出了很大改进,但仍然没有像编译时验证 (compile-time verification) 或受检查的异常 (checked exceptions) 那样的安全网来告诉你何时出现错误。关于并发,你只能依靠自己,只有知识渊博、保持怀疑和积极进取的人,才能用 Java 编写可靠的并发代码。
+
## 并发为速度而生
在听说并发编程的问题之后,你可能会想知道它是否值得这么麻烦。答案是“不,除非你的程序运行速度不够快。”并且在决定用它之前你会想要仔细思考。不要随便跳进并发编程的悲痛之中。如果有一种方法可以在更快的机器上运行你的程序,或者如果你可以对其进行分析并发现瓶颈并在该位置替换更快的算法,那么请执行此操作。只有在显然没有其他选择时才开始使用并发,然后仅在必要的地方去使用它。
From 7285c0229f016255e0afb15fc57303c81e7666f3 Mon Sep 17 00:00:00 2001
From: KIDlty
Date: Sun, 27 Sep 2020 10:20:27 +0800
Subject: [PATCH 23/68] Update 00-Preface.md (#598)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
For this I might
receive criticism for using “toy examples,” but I’m willing to
accept that in favor of producing something pedagogically useful. 翻译修正
---
docs/book/00-Preface.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/book/00-Preface.md b/docs/book/00-Preface.md
index 903b92e5..0e2ccbd0 100644
--- a/docs/book/00-Preface.md
+++ b/docs/book/00-Preface.md
@@ -17,7 +17,7 @@
1. 循序渐进地呈现学习内容,以便于你在不依赖后置知识框架的情况下轻松完成现有的学习任务,同时尽量保证前面章节的内容在后面的学习中得到运用。如果确有必要引入我们还没学习到的知识概念,我会做个简短地介绍。
-2. 尽可能地使用简单和简短的示例,方便读者理解。而不强求引入解决实际问题的例子。因为我发现,相比解决某个实际问题,读者更乐于看到自己真正理解了示例的每个细节。或许我会因为这些“玩具示例”而被一些人所诟病,但我更愿意看到我的读者们因此能保持饶有兴趣地学习。
+2. 尽可能地使用简单和简短的示例,方便读者理解。而不强求引入解决实际问题的例子。因为我发现,相比解决某个实际问题,读者更乐于看到自己真正理解了示例的每个细节。或许我会因为这些“玩具示例”而被一些人所诟病,但我更愿意相信这样的教学方式更加有效。
3. 把我知道以及我认为对于你学习语言很重要的东西都告诉你。我认为信息的重要性是分层次结构的。绝大多数情况下,我们没必要弄清问题的所有本质。好比编程语言中的某些特性和实现细节,95% 的程序员都不需要去知道。这些细节除了会加重你的学习成本,还让你更觉得这门语言好复杂。如果你非要考虑这些细节,那么它还会迷惑该代码的阅读者/维护者,所以我主张选择简单的方法解决问题。
From 8fcffc3cdb15cf12ff0d75af529797bc10a78c24 Mon Sep 17 00:00:00 2001
From: jangbeyond <70657747+jangbeyond@users.noreply.github.com>
Date: Sun, 27 Sep 2020 15:55:20 +0800
Subject: [PATCH 24/68] =?UTF-8?q?=E7=AC=AC=E5=8D=81=E5=9B=9B=E7=AB=A0=20?=
=?UTF-8?q?=E4=BF=AE=E6=AD=A3Optional=E7=B1=BB=E6=A0=87=E9=A2=98=E4=B8=8B?=
=?UTF-8?q?=E7=9A=84=E7=AC=AC=E4=B8=80=E6=AE=B5=20(#595)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* 修正Optional类标题下的第一段
这段的译文确实不太好懂,所以我尝试着修改了一下。
不过,Happy Path 这个词没似乎没有正式的术语。
有道词典显示,有36个网页翻译成了「快乐路径」,有4个网页翻译成了「愉悦路径」,因此我采取了「快乐路径」这个译法。
* Update 14-Streams.md
空流应该还是更准确一点吧。。。囧
* Change the position of the footnote....
---
docs/book/14-Streams.md | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/docs/book/14-Streams.md b/docs/book/14-Streams.md
index f3d85cef..ba2fd7c6 100644
--- a/docs/book/14-Streams.md
+++ b/docs/book/14-Streams.md
@@ -1138,7 +1138,7 @@ is it
## Optional类
-在我们学习终端操作(Terminal Operations)之前,我们必须考虑如果你在一个空流中获取元素会发生什么。我们喜欢为了“happy path”而将流连接起来,并假设流不会被中断。在流中放置 `null` 是很好的中断方法。那么是否有某种对象,可作为流元素的持有者,即使查看的元素不存在也能友好地提示我们(也就是说,不会发生异常)?
+在我们学习终端操作(Terminal Operations)之前,我们必须考虑在一个空流中获取元素会发生什么。我们喜欢沿着“快乐路径”[^1]把流连接起来,同时假设流不会中断。然而,在流中放置 `null` 却会轻易令其中断。那么是否存在某种对象,可以在持有流元素的同时,即使在我们查找的元素不存在时,也能友好地对我们进行提示(也就是说,不会产生异常)?
**Optional** 可以实现这样的功能。一些标准流操作返回 **Optional** 对象,因为它们并不能保证预期结果一定存在。包括:
@@ -2144,6 +2144,8 @@ IntSummaryStatistics{count=100, sum=50794, min=8, average=507.940000, max=998}
流式操作改变并极大地提升了 Java 语言的可编程性,并可能极大地阻止了 Java 编程人员向诸如 Scala 这种函数式语言的流转。在本书的剩余部分,我们将尽可能地使用流。
+[^1]: 在软件或信息建模的上下文中,快乐路径(有时称为快乐流)是没有异常或错误条件的默认场景。例如,验证信用卡号的函数的快乐路径应该是任何验证规则都不会出现错误的地方,从而让执行成功地继续到最后,生成一个积极的响应。[见 wikipedia: happy path](https://en.wikipedia.org/wiki/Happy_path)
+
From f70058c853556e474aa7b7e6c7e16086f62379fd Mon Sep 17 00:00:00 2001
From: Xingkai Yu <38156925+GeekEmperor@users.noreply.github.com>
Date: Mon, 28 Sep 2020 16:21:40 +0800
Subject: [PATCH 25/68] =?UTF-8?q?Fix=20issue=20#596:=20=E7=AC=AC=E5=85=AB?=
=?UTF-8?q?=E7=AB=A0=E5=92=8C=E7=AC=AC=E4=B9=9D=E7=AB=A0=E5=9B=BE=E7=89=87?=
=?UTF-8?q?=E9=94=99=E4=BD=8D=20(#600)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
docs/book/08-Reuse.md | 2 +-
docs/book/09-Polymorphism.md | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/book/08-Reuse.md b/docs/book/08-Reuse.md
index baad9ac2..2e37dabf 100644
--- a/docs/book/08-Reuse.md
+++ b/docs/book/08-Reuse.md
@@ -869,7 +869,7 @@ public class Wind extends Instrument {
该术语是基于传统的类继承图:图最上面是根,然后向下铺展。(当然你可以以任意方式画你认为有帮助的类图。)于是,**Wind.java** 的类图是:
-
+
继承图中派生类转型为基类是向上的,所以通常称作*向上转型*。因为是从一个更具体的类转化为一个更一般的类,所以向上转型永远是安全的。也就是说,派生类是基类的一个超集。它可能比基类包含更多的方法,但它必须至少具有与基类一样的方法。在向上转型期间,类接口只可能失去方法,不会增加方法。这就是为什么编译器在没有任何明确转型或其他特殊标记的情况下,仍然允许向上转型的原因。
diff --git a/docs/book/09-Polymorphism.md b/docs/book/09-Polymorphism.md
index 6a105c6a..63075630 100644
--- a/docs/book/09-Polymorphism.md
+++ b/docs/book/09-Polymorphism.md
@@ -184,7 +184,7 @@ Java 中除了 **static** 和 **final** 方法(**private** 方法也是隐式
形状的例子中,有一个基类称为 **Shape** ,多个不同的派生类型分别是:**Circle**,**Square**,**Triangle** 等等。这个例子之所以好用,是因为我们可以直接说“圆(Circle)是一种形状(Shape)”,这很容易理解。继承图展示了它们之间的关系:
-
+
向上转型就像下面这么简单:
From 7dc616e6d7e878269883db18b6784e43135b9ece Mon Sep 17 00:00:00 2001
From: TENCHIANG
Date: Wed, 30 Sep 2020 10:49:34 +0800
Subject: [PATCH 26/68] =?UTF-8?q?=E7=BF=BB=E8=AF=91=E4=BC=98=E5=8C=96=2024?=
=?UTF-8?q?-Concurrent-Programming.md#=E5=B9=B6=E5=8F=91=E4=B8=BA=E9=80=9F?=
=?UTF-8?q?=E5=BA=A6=E8=80=8C=E7=94=9F=20#Java=20=E5=B9=B6=E5=8F=91?=
=?UTF-8?q?=E7=9A=84=E5=9B=9B=E5=8F=A5=E6=A0=BC=E8=A8=80=20(#597)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* 翻译优化 24-Concurrent-Programming.md#并发为速度而生 #Java 并发的四句格言
* 翻译优化 24-Concurrent-Programming.md#并发为速度而生 #Java 并发的四句格言 fix翻译错误
---
docs/book/24-Concurrent-Programming.md | 78 +++++++++++++-------------
1 file changed, 39 insertions(+), 39 deletions(-)
diff --git a/docs/book/24-Concurrent-Programming.md b/docs/book/24-Concurrent-Programming.md
index f0eaa0d2..e8ed661e 100755
--- a/docs/book/24-Concurrent-Programming.md
+++ b/docs/book/24-Concurrent-Programming.md
@@ -135,91 +135,91 @@ slowdown occurs):
在听说并发编程的问题之后,你可能会想知道它是否值得这么麻烦。答案是“不,除非你的程序运行速度不够快。”并且在决定用它之前你会想要仔细思考。不要随便跳进并发编程的悲痛之中。如果有一种方法可以在更快的机器上运行你的程序,或者如果你可以对其进行分析并发现瓶颈并在该位置替换更快的算法,那么请执行此操作。只有在显然没有其他选择时才开始使用并发,然后仅在必要的地方去使用它。
-速度问题一开始听起来很简单:如果你想要一个程序运行得更快,将其分解成碎片并在一个单独的处理器上运行每个部分。由于我们能够提高时钟速度流(至少对于传统芯片),速度的提高是出现在多核处理器的形式而不是更快的芯片。为了使你的程序运行得更快,你必须学会如何利用那些额外的处理器,这是并发性给你的一个建议。
+速度问题一开始听起来很简单:如果你想要一个程序运行得更快,将其分解为多个部分,并在单独的处理器上运行每个部分。随着我们提高时钟速度的能力耗尽(至少对传统芯片而言),速度的提高是出现在多核处理器的形式而不是更快的芯片。为了使程序运行得更快,你必须学会利用那些额外的处理器(译者注:处理器一般代表 CPU 的一个逻辑核心),这是并发所带来的好处之一。
-使用多处理器机器,可以在这些处理器之间分配多个任务,这可以显着提高吞吐量。强大的多处理器 Web 服务器通常就是这种情况,它可以在程序中为 CPU 分配大量用户请求,每个请求分配一个线程。
+对于多处理器机器,可以在这些处理器之间分配多个任务,这可以显著提高吞吐量。强大的多处理器 Web 服务器通常就是这种情况,它可以在程序中为 CPU 分配大量用户请求,每个请求分配一个线程。
-但是,并发性通常可以提高在单个处理器上运行的程序的性能。这听起来有点违反直觉。如果考虑一下,由于上下文切换的成本增加(从一个任务更改为另一个任务),在单个处理器上运行的并发程序实际上应该比程序的所有部分顺序运行具有更多的开销。在表面上,将程序的所有部分作为单个任务运行并节省上下文切换的成本似乎更便宜。
+但是,并发通常可以提高在单处理器上运行的程序的性能。这听起来有点违反直觉。如果你仔细想想,由于上下文切换的成本增加(从一个任务切换到另一个任务),在单个处理器上运行的并发程序实际上应该比程序的所有部分顺序运行具有更多的开销。从表面上看,将程序的所有部分作为单个任务运行,并且节省上下文切换的成本,这样看似乎更划算。
-可以产生影响的问题是阻塞。如果你的程序中的一个任务由于程序控制之外的某些条件(通常是 I/O)而无法继续,我们会说任务或线程阻塞(在我们的科幻故事中,克隆体已敲门而且是等待它打开)。如果没有并发性,整个程序就会停止,直到外部条件发生变化。但是,如果使用并发编写程序,则当一个任务被阻止时,程序中的其他任务可以继续执行,因此程序继续向前移动。实际上,从性能的角度来看,在单处理器机器上使用并发是没有意义的,除非其中一个任务可能阻塞。
+使这个问题变得有些不同的是阻塞。如果程序中的某个任务由于程序控制之外的某种情况而无法继续(通常是 I/O),我们就称该任务或线程已阻塞(在我们的科幻故事中,就是克隆人已经敲门并等待它打开)。如果没有并发,整个程序就会停下来,直到外部条件发生变化。但是,如果使用并发编写程序,则当一个任务被阻塞时,程序中的其他任务可以继续执行,因此整个程序得以继续运行。事实上,从性能的角度来看,如果没有任务会阻塞,那么在单处理器机器上使用并发是没有意义的。
-单处理器系统中性能改进的一个常见例子是事件驱动编程,特别是用户界面编程。考虑一个程序执行一些长时间运行操作,从而最终忽略用户输入和无响应。如果你有一个“退出”按钮,你不想在你编写的每段代码中轮询它。这会产生笨拙的代码,无法保证程序员不会忘记执行检查。没有并发性,生成响应式用户界面的唯一方法是让所有任务定期检查用户输入。通过创建单独的执行线程来响应用户输入,该程序保证了一定程度的响应。
+单处理器系统中性能改进的一个常见例子是事件驱动编程,特别是用户界面编程。考虑一个程序执行一些耗时操作,最终忽略用户输入导致无响应。如果你有一个“退出”按钮,你不想在你编写的每段代码中都检查它的状态(轮询)。这会产生笨拙的代码,也无法保证程序员不会忘了检查。没有并发,生成可响应用户界面的唯一方法是让所有任务都定期检查用户输入。通过创建单独的线程以执行用户输入的响应,能够让程序保证一定程度的响应能力。
-实现并发的直接方法是在操作系统级别,使用与线程不同的进程。进程是一个在自己的地址空间内运行的自包含程序。进程很有吸引力,因为操作系统通常将一个进程与另一个进程隔离,因此它们不会相互干扰,这使得进程编程相对容易。相比之下,线程共享内存和 I/O 等资源,因此编写多线程程序时遇到的困难是在不同的线程驱动的任务之间协调这些资源,一次不能通过多个任务访问它们。
+实现并发的一种简单方式是使用操作系统级别的进程。与线程不同,进程是在其自己的地址空间中运行的独立程序。进程的优势在于,因为操作系统通常将一个进程与另一个进程隔离,因此它们不会相互干扰,这使得进程编程相对容易。相比之下,线程之间会共享内存和 I/O 等资源,因此编写多线程程序最基本的困难,在于协调不同线程驱动的任务之间对这些资源的使用,以免这些资源同时被多个任务访问。
-有些人甚至提倡将进程作为并发的唯一合理方法[^1],但不幸的是,通常存在数量和开销限制,从而阻止了在并发范围内的适用性(最终你会习惯标准的并发限制,“这种方法适用于一些情况但不适用于其他情况”)
+有些人甚至提倡将进程作为唯一合理的并发实现方式[^1],但遗憾的是,通常存在数量和开销方面的限制,从而阻止了进程在并发范围内的适用性(最终你会习惯标准的并发限制,“这种方法适用于一些情况但不适用于其他情况”)
-一些编程语言旨在将并发任务彼此隔离。这些通常被称为_函数式语言_,其中每个函数调用不产生其他影响(因此不能与其他函数干涉),因此可以作为独立的任务来驱动。Erlang 就是这样一种语言,它包括一个任务与另一个任务进行通信的安全机制。如果你发现程序的某一部分必须大量使用并发性并且你在尝试构建该部分时遇到了过多的问题,那么你可能会考虑使用专用并发语言创建程序的那一部分。
+一些编程语言旨在将并发任务彼此隔离。这些通常被称为_函数式语言_,其中每个函数调用不产生副作用(不会干扰到其它函数),所以可以作为独立的任务来驱动。Erlang 就是这样一种语言,它包括一个任务与另一个任务进行通信的安全机制。如果发现程序的某一部分必须大量使用并发,并且在尝试构建该部分时遇到了过多的问题,那么可以考虑使用这些专用的并发语言创建程序的这个部分。
-Java 采用了更传统的方法[^2],即在顺序语言之上添加对线程的支持而不是在多任务操作系统中分配外部进程,线程在执行程序所代表的单个进程中创建任务交换。
+Java 采用了更传统的方法[^2],即在顺序语言之上添加对线程的支持而不是在多任务操作系统中分叉外部进程,线程是在表示执行程序的单个进程内创建任务。
-并发性会带来成本,包括复杂性成本,但可以通过程序设计,资源平衡和用户便利性的改进来抵消。通常,并发性使你能够创建更加松散耦合的设计;除此以外,你必须特别关注那些使用了并发操作的代码。
+并发会带来各种成本,包括复杂性成本,但可以被程序设计、资源平衡和用户便利性方面的改进所抵消。通常,并发性使你能够创建更低耦合的设计;另一方面,你必须特别关注那些使用了并发操作的代码。
-## 四句格言
+## Java 并发的四句格言
-在经历了多年的 Java 并发之后,我总结了以下四个格言:
->1.不要这样做
+在经历了多年 Java 并发的实践之后,我总结了以下四个格言:
+>1.不要用它(避免使用并发)
>
>2.没有什么是真的,一切可能都有问题
>
->3.它起作用,并不意味着它没有问题
+>3.仅仅是它能运行,并不意味着它没有问题
>
->4.你仍然必须理解它
+>4.你必须理解它(逃不掉并发)
这些格言专门针对 Java 的并发设计问题,尽管它们也可以适用于其他一些语言。但是,确实存在旨在防止这些问题的语言。
-### 1.不要这样做
+### 1.不要用它
-(不要自己动手)
+(而且不要自己去实现它)
-避免纠缠于并发产生的深层问题的最简单方法就是不要这样做。虽然它是诱人的,并且在做一些简单的事情时似乎足够安全,但它存在无数、微妙的陷阱。如果你可以避免它,你的生活会更容易。
+避免陷入并发所带来的玄奥问题的最简单方法就是不要用它。尽管尝试一些简单的东西可能很诱人,也似乎足够安全,但是陷阱却是无穷且微妙的。如果你能避免使用它,你的生活将会轻松得多。
-证明并发性的唯一因素是速度。如果你的程序运行速度不够快 - 在这里要小心,因为只是希望它运行得更快是不合理的 - 应该首先用一个分析器(参见代码校验章中分析和优化)来发现你是否可以执行其他一些优化。
+使用并发唯一的正当理由是速度。如果你的程序运行速度不够快——这里要小心,因为仅仅想让它运行得更快不是正当理由——应该首先用一个分析器(参见代码校验章中分析和优化)来发现你是否可以执行其他一些优化。
-如果你被迫进行并发,请采取最简单,最安全的方法来解决问题。使用众所周知的库并尽可能少地编写自己的代码。有了并发性,就没有“太简单了”。自负才是你的敌人。
+如果你被迫使用并发,请采取最简单,最安全的方法来解决问题。使用知名的库并尽可能少地自己编写代码。对于并发,就没有“太简单了”——自作聪明是你的敌人。
### 2.没有什么是真的,一切可能都有问题
-没有并发性的编程,你会发现你的世界有一定的顺序和一致性。通过简单地将变量赋值给某个值,很明显它应该始终正常工作。
+不使用并发编程,你已经预料到你的世界具有确定的顺序和一致性。对于变量赋值这样简单的操作,很明显它应该总是能够正常工作。
-在并发领域,有些事情可能是真的而有些事情却不是,你必须认为没有什么是真的。你必须质疑一切。即使将变量设置为某个值也可能或者可能不会按预期的方式工作,并且从那里开始走下坡路。对于在并发中遇到那些看起来有效但实际上无效的东西,我已经很习惯了。
+在并发领域,有些事情可能是真的而有些事情却不是,以至于你必须假设没有什么是真的。你必须质疑一切。即使将变量设置为某个值也可能不会按预期的方式工作,事情从这里开始迅速恶化。我已经熟悉了这样一种感觉:我认为应该明显奏效的东西,实际上却行不通。
-在非并发程序中你可以忽略的各种事情在并发程序中突然变得非常重要。例如,你必须知道处理器缓存以及保持本地缓存与主内存一致的问题。你必须深入了解对象构造的复杂性,以便你的构造器不会意外地将数据暴露给其他线程进行更改。问题还有很多。
+在非并发编程中你可以忽略的各种事情,在并发下突然变得很重要。例如,你必须了解处理器缓存以及保持本地缓存与主内存一致的问题,你必须理解对象构造的深层复杂性,这样你的构造函数就不会意外地暴露数据,以致于被其它线程更改。这样的例子不胜枚举。
-因为这些主题太复杂,本章无法为你提供更专业的知识(再次参见 Java Concurrency in Practice),但你必须了解它们。
+虽然这些主题过于复杂,无法在本章中给你提供专业知识(同样,请参见 Java Concurrency in Practice),但你必须了解它们。
-### 3.它起作用,并不意味着它没有问题
+### 3.仅仅是它能运行,并不意味着它没有问题
-我们很容易编写出一个看似完美实则有问题的并发程序,并且往往问题直在极端情况下才暴露出来 - 在程序部署后不可避免地会出现用户问题。
+我们很容易编写出一个看似正常实则有问题的并发程序,而且问题只有在极少的情况下才会显现出来——在程序部署后不可避免地会成为用户问题(投诉)。
-- 你不能证明并发程序是正确的,你只能(有时)证明它是不正确的。
-- 大多数情况下你甚至不能这样做:如果它有问题,你可能无法检测到它。
-- 你通常不能编写有用的测试,因此你必须依靠代码检查结合深入的并发知识来发现错误。
+- 你不能验证出并发程序是正确的,你只能(有时)验证出它是不正确的。
+- 大多数情况下你甚至没办法验证:如果它出问题了,你可能无法检测到它。
+- 你通常无法编写有用的测试,因此你必须依靠代码检查和对并发的深入了解来发现错误。
- 即使是有效的程序也只能在其设计参数下工作。当超出这些设计参数时,大多数并发程序会以某种方式失败。
-在其他 Java 主题中,我们培养了一种感觉-决定论。一切都按照语言的承诺(或隐含)进行,这是令人欣慰和期待的 - 毕竟,编程语言的目的是让机器做我们想要的。从确定性编程的世界进入并发编程领域,我们遇到了一种称为[Dunning-Kruger](https://en.wikipedia.org/wiki/Dunning%E2%80%93Kruger_effect) 效应的认知偏差,可以概括为“无知者无畏。”这意味着“......相对不熟练的人拥有着虚幻的优越感,错误地评估他们的能力远高于实际。
+在其他 Java 主题中,我们养成了决定论的观念。一切都按照语言的承诺的(或暗示的)发生,这是令人欣慰的也是人们所期待的——毕竟,编程语言的意义就是让机器做我们想要它做的事情。从确定性编程的世界进入并发编程领域,我们遇到了一种称为 [邓宁-克鲁格效应](https://en.wikipedia.org/wiki/Dunning%E2%80%93Kruger_effect) 的认知偏差,可以概括为“无知者无畏”,意思是:“相对不熟练的人拥有着虚幻的优越感,错误地评估他们的能力远高于实际。
-我自己的经验是,无论你是多么确定你的代码是线程安全的,它可能已经无效了。你可以很容易地了解所有的问题,然后几个月或几年后你会发现一些概念让你意识到你编写的大多数内容实际上都容易受到并发错误的影响。当某些内容不正确时,编译器不会告诉你。为了使它正确,你必须在研究代码前了解所有并发问题。
+我自己的经验是,无论你是多么确定你的代码是_线程安全_的,它都可能是有问题的。你可以很容易地了解所有的问题,然后几个月或几年后你会发现一些概念,让你意识到你编写的大多数代码实际上都容易受到并发 bug 的影响。当某些代码不正确时,编译器不会告诉你。为了使它正确,在研究代码时,必须将并发性的所有问题都放在前脑中。
-在 Java 的所有非并发领域,“没有明显的错误和没有明显的编译错误”似乎意味着一切都好。对于并发,它没有任何意义。在这种情况你最糟糕的表现就是“自信”。
+在 Java 的所有非并发领域,“没有明显的 bug 而且没有编译报错“似乎意味着一切都好。但对于并发,它没有任何意义。在这种情况你最糟糕的表现就是“自信”。
-### 4.你必须仍然理解
+### 4.你必须理解它
在格言 1-3 之后,你可能会对并发性感到害怕,并且认为,“到目前为止,我已经避免了它,也许我可以继续避免它。
-这是一种理性的反应。你可能知道其他编程语言更好地设计用于构建并发程序 - 甚至是在 JVM 上运行的程序(从而提供与 Java 的轻松通信),例如 Clojure 或 Scala。为什么不用这些语言编写并发部分并将 Java 用于其他所有部分呢?
+这是一种理性的反应。你可能知道其他更好地被设计用于构建并发程序的编程语言——甚至是在 JVM 上运行的语言(从而提供与 Java 的轻松通信),例如 Clojure 或 Scala。为什么不用这些语言来编写并发部分,然后用Java来做其他的事情呢?
唉,你不能轻易逃脱:
-- 即使你从未明确地创建一个线程,你可能使用的框架 - 例如,Swing 图形用户界面(GUI)库,或者像 **Timer** class 那样简单的东西。
-- 这是最糟糕的事情:当你创建组件时,你必须假设这些组件可能在多线程环境中重用。即使你的解决方案是放弃并声明你的组件“不是线程安全的”,你仍然必须知道这样的声明是重要的,它是什么意思?
+- 即使你从未显示地创建一个线程,你使用的框架也可能——例如,Swing 图形用户界面(GUI)库,或者像 **Timer** 类(计时器)那样简单的东西。
+- 最糟糕的是:当你创建组件时,必须假设这些组件可能会在多线程环境中重用。即使你的解决方案是放弃并声明你的组件是“非线程安全的”,你仍然必须充分了解这样一个语句的重要性及其含义。
-人们有时会认为并发性太难,不能包含在介绍该语言的书中。他们认为并发是一个可以独立对待的独立主题,并且它在日常编程中出现的少数情况(例如图形用户界面)可以用特殊的习语来处理。如果你可以避免它,为什么要介绍这样的复杂的主题。
+人们有时会认为并发对于介绍语言的书来说太高级了,因此不适合放在其中。他们认为并发是一个独立的主题,并且对于少数出现在日常的程序设计中的情况(例如图形用户界面),可以用特殊的惯用法来处理。如果你可以回避,为什么还要介绍这么复杂的主题呢?
-唉,如果只是这样的话,那就太好了。但不幸的是,你无法选择何时在 Java 程序中出现线程。仅仅你从未写过自己的线程,并不意味着你可以避免编写线程代码。例如,Web 系统是最常见的 Java 应用程序之一,本质上是多线程的 Web 服务器通常包含多个处理器,而并行性是利用这些处理器的理想方式。就像这样的系统看起来那么简单,你必须理解并发才能正确地编写它。
+唉,如果是这样就好了。遗憾的是,对于线程何时出现在 Java 程序中,这不是你能决定的。仅仅是你自己没有启动线程,并不代表你就可以回避编写使用线程的代码。例如,Web 系统是最常见的 Java 应用之一,本质上是多线程的 Web 服务器,通常包含多个处理器,而并行是利用这些处理器的理想方式。尽管这样的系统看起来很简单,但你必须理解并发才能正确地编写它。
-Java 是一种多线程语言,不管你有没有意识到并发问题,它就在那里。因此,有许多 Java 程序正在使用中,或者只是偶然工作,或者大部分时间工作并且不时地发生问题,因为。有时这种问题是相对良性的,但有时它意味着丢失有价值的数据,如果你没有意识到并发问题,你最终可能会把问题放在其他地方而不是你的代码中。如果将程序移动到多处理器系统,则可以暴露或放大这些类型的问题。基本上,了解并发性使你意识到正确的程序可能会表现出错误的行为。
+Java 是一种多线程语言,不管你有没有意识到并发问题,它就在那里。因此,有很多使用并发的 Java 程序,要么只是偶然运行,要么大部分时间都在运行,并且会因为未被发现的并发缺陷而时不时地神秘崩溃。有时这种崩溃是相对温和的,但有时它意味着丢失有价值的数据,如果你没有意识到并发问题,你最终可能会把问题归咎于其他地方而不是你的代码中。如果将程序移动到多处理器系统中,这些类型的问题还会被暴露或放大。基本上,了解并发可以使你意识到明显正确的程序也可能会表现出错误的行为。
## 残酷的真相
From 0434fa9c4906d4eae82e5808ecc2e5943a625865 Mon Sep 17 00:00:00 2001
From: Hongkuan Wang
Date: Fri, 9 Oct 2020 10:37:18 +0800
Subject: [PATCH 27/68] fix typo (#603)
---
docs/book/Appendix-Object-Serialization.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/docs/book/Appendix-Object-Serialization.md b/docs/book/Appendix-Object-Serialization.md
index 722f0e51..648373bd 100644
--- a/docs/book/Appendix-Object-Serialization.md
+++ b/docs/book/Appendix-Object-Serialization.md
@@ -199,7 +199,7 @@ class Alien
正如大家所看到的,默认的序列化机制并不难操纵。然而,如果有特殊的需要那又该怎么办呢?例如,也许要考虑特殊的安全问题,而且你不希望对象的某一部分被序列化;或者一个对象被还原以后,某子对象需要重新创建,从而不必将该子对象序列化。
-在这些特殊情况下,可通过实现 Externalizable 接口——代替实现 Serializable 接口-来对序列化过程进行控制。这个 Externalizable 接口继承了 Serializable 接口,同时增添了两个方法:writeExternal0 和 readExternal0。这两个方法会在序列化和反序列化还原的过程中被自动调用,以便执行一些特殊操作。
+在这些特殊情况下,可通过实现 Externalizable 接口——代替实现 Serializable 接口-来对序列化过程进行控制。这个 Externalizable 接口继承了 Serializable 接口,同时增添了两个方法:writeExternal() 和 readExternal()。这两个方法会在序列化和反序列化还原的过程中被自动调用,以便执行一些特殊操作。
下面这个例子展示了 Externalizable 接口方法的简单实现。注意 Blip1 和 Blip2 除了细微的差别之外,几乎完全一致(研究一下代码,看看你能否发现):
@@ -366,7 +366,7 @@ Blip3.readExternal
A String 47
```
-其中,字段 s 和只在第二个构造器中初始化,而不是在默认的构造器中初始化。这意味着假如不在 readExternal0 中初始化 s 和 i,s 就会为 null,而就会为零(因为在创建对象的第一步中将对象的存储空间清理为 0)。如果注释掉跟随于"You must do this”后面的两行代码,然后运行程序,就会发现当对象被还原后,s 是 null,而 i 是零。
+其中,字段 s 和 i 只在第二个构造器中初始化,而不是在默认的构造器中初始化。这意味着假如不在 readExternal() 中初始化 s 和 i,s 就会为 null,而 i 就会为零(因为在创建对象的第一步中将对象的存储空间清理为 0)。如果注释掉跟随于"You must do this”后面的两行代码,然后运行程序,就会发现当对象被还原后,s 是 null,而 i 是零。
我们如果从一个 Externalizable 对象继承,通常需要调用基类版本的 writeExternal() 和 readExternal() 来为基类组件提供恰当的存储和恢复功能。
@@ -552,7 +552,7 @@ writeObject() 方法必须检查 sc,判断它是否拥有自己的 writeObject
## 使用持久化
-个比较诱人的使用序列化技术的想法是:存储程序的一些状态,以便我们随后可以很容易地将程序恢复到当前状态。但是在我们能够这样做之前,必须回答几个问题。如果我们将两个对象-它们都具有指向第三个对象的引用-进行序列化,会发生什么情况?当我们从它们的序列化状态恢复这两个对象时,第三个对象会只出现一次吗?如果将这两个对象序列化成独立的文件,然后在代码的不同部分对它们进行反序列化还原,又会怎样呢?
+一个比较诱人的使用序列化技术的想法是:存储程序的一些状态,以便我们随后可以很容易地将程序恢复到当前状态。但是在我们能够这样做之前,必须回答几个问题。如果我们将两个对象-它们都具有指向第三个对象的引用-进行序列化,会发生什么情况?当我们从它们的序列化状态恢复这两个对象时,第三个对象会只出现一次吗?如果将这两个对象序列化成独立的文件,然后在代码的不同部分对它们进行反序列化还原,又会怎样呢?
下面这个例子说明了上述问题:
From 71ff462b5df21cbe49437f4443ee976ae481b371 Mon Sep 17 00:00:00 2001
From: Hongkuan Wang
Date: Fri, 9 Oct 2020 10:37:39 +0800
Subject: [PATCH 28/68] fix typo (#602)
---
docs/book/Appendix-New-IO.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/docs/book/Appendix-New-IO.md b/docs/book/Appendix-New-IO.md
index 94e47660..2f49f3e5 100644
--- a/docs/book/Appendix-New-IO.md
+++ b/docs/book/Appendix-New-IO.md
@@ -4,7 +4,7 @@
# 附录:新IO
-> Java 新I/O 库是在 1.4 版本引入到 `Java .nio.* package` 中的,旨在更快速。
+> Java 新I/O 库是在 1.4 版本引入到 `java.nio.*` 包中的,旨在更快速。
实际上,新 I/O 使用 **NIO**(同步非阻塞)的方式重写了老的 I/O 了,因此它获得了 **NIO** 的种种优点。即使我们不显式地使用 **NIO** 方式来编写代码,也能带来性能和速度的提高。这种提升不仅仅体现在文件读写(File I/O),同时也体现在网络读写(Network I/O)中。例如,网络编程。
@@ -88,7 +88,7 @@ Some text Some more
将字节放入 **ByteBuffer** 的一种方法是直接调用 `put()` 方法将一个或多个字节放入 **ByteBuffer**;当然也可以是其它基本类型的数据。此外,参考上例,我们还可以调用 `wrap()` 方法包装现有字节数组到 **ByteBuffer**。执行此操作时,不会复制底层数组,而是将其用作生成的 **ByteBuffer** 存储。这样产生的 **ByteBuffer** 是数组“支持”的。
-data.txt 文件被 **RandomAccessFile** 重新打开。**注意**,你可以在文件中移动 **FileChanne**。 在这里,它被移动到末尾,以便添加额外的写操作。
+data.txt 文件被 **RandomAccessFile** 重新打开。**注意**,你可以在文件中移动 **FileChannel**。 在这里,它被移动到末尾,以便添加额外的写操作。
对于只读访问,必须使用静态 `allocate()` 方法显式地分配 **ByteBuffer**。**NIO** 的目标是快速移动大量数据,因此 **ByteBuffer** 的大小应该很重要 —— 实际上,这里设置的 1K 都可能偏小了(我们在工作中应该反复测试以找到最佳大小)。
@@ -175,7 +175,7 @@ public class TransferTo {
## 数据转换
-为了将 **GetChannel.java** 文件中的信息打印出来。在 Java 中,我们每次提取一个字节的数据并将其转换为字符。看起来很简单 —— 如果你有看过 `ava.nio.`**CharBuffer** 类,你会发现一个 `toString()` 方法。该方法的作用是“返回一个包含此缓冲区字符的字符串”。
+为了将 **GetChannel.java** 文件中的信息打印出来。在 Java 中,我们每次提取一个字节的数据并将其转换为字符。看起来很简单 —— 如果你有看过 `java.nio.`**CharBuffer** 类,你会发现一个 `toString()` 方法。该方法的作用是“返回一个包含此缓冲区字符的字符串”。
既然 **ByteBuffer** 可以通过 **CharBuffer** 类的 `asCharBuffer()` 方法查看,那我们就来尝试一样。从下面输出语句的第一行可以看出,这并不正确:
From 35a32719aa89d20b2b6f197c32678cda13c9e85a Mon Sep 17 00:00:00 2001
From: Hongkuan Wang
Date: Fri, 9 Oct 2020 16:11:51 +0800
Subject: [PATCH 29/68] Remove redundant \ (#604)
---
docs/book/18-Strings.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/docs/book/18-Strings.md b/docs/book/18-Strings.md
index 151eed10..b75429c5 100755
--- a/docs/book/18-Strings.md
+++ b/docs/book/18-Strings.md
@@ -801,10 +801,10 @@ the mightiest banana in the forest...with... a banana!
| 表达式 | 含义 |
| :---- | :---- |
| `.` | 任意字符 |
-| `[abc]` |包含`a`、`b`或`c`的任何字符(和`a\|b\|c`作用相同)|
+| `[abc]` |包含`a`、`b`或`c`的任何字符(和`a|b|c`作用相同)|
| `[^abc]` | 除`a`、`b`和`c`之外的任何字符(否定) |
| `[a-zA-Z]` | 从`a`到`z`或从`A`到`Z`的任何字符(范围) |
-| `[abc[hij]]` | `a`、`b`、`c`、`h`、`i`、`j`中的任意字符(与`a\|b\|c\|h\|i\|j`作用相同)(合并) |
+| `[abc[hij]]` | `a`、`b`、`c`、`h`、`i`、`j`中的任意字符(与`a|b|c|h|i|j`作用相同)(合并) |
| `[a-z&&[hij]]` | 任意`h`、`i`或`j`(交) |
| `\s` | 空白符(空格、tab、换行、换页、回车) |
| `\S` | 非空白符(`[^\s]`) |
@@ -818,7 +818,7 @@ the mightiest banana in the forest...with... a banana!
| 逻辑操作符 | 含义 |
| :----: | :---- |
| `XY` | `Y`跟在`X`后面 |
-| `X\|Y` | `X`或`Y` |
+| `X|Y` | `X`或`Y` |
| `(X)` | 捕获组(capturing group)。可以在表达式中用`\i`引用第i个捕获组 |
下面是不同的边界匹配符:
From 88af6850893d288b02227e35af8c70b2312e9f1a Mon Sep 17 00:00:00 2001
From: DING-Weibing <57584830+DING-Weibing@users.noreply.github.com>
Date: Mon, 12 Oct 2020 00:29:36 +0900
Subject: [PATCH 30/68] =?UTF-8?q?"=E5=8F=97=E4=BF=9D=E6=8A=A4"=EF=BC=8C?=
=?UTF-8?q?=E6=9C=89=E6=AD=A7=E4=B9=89=EF=BC=8C=E5=B9=B6=E4=B8=94=E4=B8=8D?=
=?UTF-8?q?=E6=98=93=E4=BA=8E=E7=90=86=E8=A7=A3=E3=80=82=E5=8E=9F=E6=96=87?=
=?UTF-8?q?=E5=AF=B9protected=E4=BD=BF=E7=94=A8=E4=BA=86=E5=8A=A0=E7=B2=97?=
=?UTF-8?q?=E5=AD=97=E4=BD=93=EF=BC=8C=E8=A1=A8=E6=98=8E=E8=BF=99=E6=98=AF?=
=?UTF-8?q?=E4=B8=AA=E4=B8=80=E4=B8=AA=E5=85=B3=E9=94=AE=E5=AD=97=EF=BC=8C?=
=?UTF-8?q?=E5=B9=B6=E9=9D=9E=E5=AD=97=E9=9D=A2=E6=84=8F=E6=80=9D=E5=8F=97?=
=?UTF-8?q?=E4=BF=9D=E6=8A=A4=E3=80=82=20(#605)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* "受保护",有歧义,并且不易于理解。原文对protected使用了加粗字体,表明这是个一个关键字,并非字面意思受保护。
* Markdown语法错误
* Markdown语法错误
* Markdown语法错误
* 没读懂原来的翻译是什么意思。
* 错句
* 没读懂原来的翻译是什么意思,这样改或许更好。
* 语义错误
---
docs/book/08-Reuse.md | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/docs/book/08-Reuse.md b/docs/book/08-Reuse.md
index 2e37dabf..824d59b9 100644
--- a/docs/book/08-Reuse.md
+++ b/docs/book/08-Reuse.md
@@ -214,7 +214,7 @@ Cleanser dilute() apply() scrub()
在这里,`Detergent.main()` 显式地调用 `Cleanser.main()`,从命令行传递相同的参数(当然,你可以传递任何字符串数组)。
-**Cleanser** 中的所有方法都是公开的。请记住,如果不使用任何访问修饰符,则成员默认为包访问权限,这只允许包内成员访问。因此,如果没有访问修饰符,那么包内的任何人都可以使用这些方法。例如,**Detergent** 就没有问题。但是,如果其他包中的类继承 **Cleanser**,则该类只能访问 **Cleanser** 的公共成员。因此,为了允许继承,一般规则是所有字段为私有,所有方法为公共。(受保护成员也允许派生类访问;你以后会知道的。)在特定的情况下,你必须进行调整,但这是一个有用的指南。
+**Cleanser** 中的所有方法都是公开的。请记住,如果不使用任何访问修饰符,则成员默认为包访问权限,这只允许包内成员访问。因此,如果没有访问修饰符,那么包内的任何人都可以使用这些方法。例如,**Detergent** 就没有问题。但是,如果其他包中的类继承 **Cleanser**,则该类只能访问 **Cleanser** 的公共成员。因此,为了允许继承,一般规则是所有字段为私有,所有方法为公共。(**protected**成员也允许派生类访问;你以后会知道的。)在特定的情况下,你必须进行调整,但这是一个有用的指南。
**Cleanser** 的接口中有一组方法: `append()`、`dilute()`、`apply()`、`scrub()` 和 `toString()`。因为 **Detergent** 是从 **Cleanser** 派生的(通过 **extends** 关键字),所以它会在其接口中自动获取所有这些方法,即使你没有在 **Detergent** 中看到所有这些方法的显式定义。那么,可以把继承看作是复用类。如在 `scrub()` 中所见,可以使用基类中定义的方法并修改它。在这里,你可以在新类中调用基类的该方法。但是在 `scrub()` 内部,不能简单地调用 `scrub()`,因为这会产生递归调用。为了解决这个问题,Java的 **super** 关键字引用了当前类继承的“超类”(基类)。因此表达式 `super.scrub()` 调用方法 `scrub()` 的基类版本。
@@ -359,7 +359,7 @@ DerivedSpaceShip extends SpaceShipControls {
```
-然而, **DerivedSpaceShip** 并不是真正的“一种” **SpaceShipControls** ,即使你“告诉” **DerivedSpaceShip** 调用 `forward()`。更准确地说,一艘宇宙飞船包含了 **SpaceShipControls **,同时 **SpaceShipControls** 中的所有方法都暴露在宇宙飞船中。委托解决了这个难题:
+然而, **DerivedSpaceShip** 并不是真正的“一种” **SpaceShipControls** ,即使你“告诉” **DerivedSpaceShip** 调用 `forward()`。更准确地说,一艘宇宙飞船包含了 **SpaceShipControls**,同时 **SpaceShipControls** 中的所有方法都暴露在宇宙飞船中。委托解决了这个难题:
```java
// reuse/SpaceShipDelegation.java
@@ -507,7 +507,7 @@ PlaceSetting constructor
### 保证适当的清理
-Java 没有 C++ 中析构函数的概念,析构函数是在对象被销毁时自动调用的方法。原因可能是,在Java中,通常是忘掉而不是销毁对象,从而允许垃圾收集器根据需要回收内存。通常这是可以的,但是有时你的类可能在其生命周期中执行一些需要清理的活动。初始化和清理章节提到,你无法知道垃圾收集器何时会被调用,甚至它是否会被调用。因此,如果你想为类清理一些东西,必须显式地编写一个特殊的方法来完成它,并确保客户端程序员知道他们必须调用这个方法。最重要的是——正如在"异常"章节中描述的——你必须通过在 **finally **子句中放置此类清理来防止异常。
+Java 没有 C++ 中析构函数的概念,析构函数是在对象被销毁时自动调用的方法。原因可能是,在Java中,通常是忘掉而不是销毁对象,从而允许垃圾收集器根据需要回收内存。通常这是可以的,但是有时你的类可能在其生命周期中执行一些需要清理的活动。初始化和清理章节提到,你无法知道垃圾收集器何时会被调用,甚至它是否会被调用。因此,如果你想为类清理一些东西,必须显式地编写一个特殊的方法来完成它,并确保客户端程序员知道他们必须调用这个方法。最重要的是——正如在"异常"章节中描述的——你必须通过在 **finally**子句中放置此类清理来防止异常。
请考虑一个在屏幕上绘制图片的计算机辅助设计系统的例子:
@@ -692,7 +692,7 @@ doh(Milhouse)
**Homer** 的所有重载方法在 **Bart** 中都是可用的,尽管 **Bart** 引入了一种新的重载方法。在下一章中你将看到,使用与基类中完全相同的签名和返回类型覆盖相同名称的方法要常见得多。否则就会令人困惑。
-你已经看到了Java 5 **@Override **注释,它不是关键字,但是可以像使用关键字一样使用它。当你打算重写一个方法时,你可以选择添加这个注释,如果你不小心用了重载而不是重写,编译器会产生一个错误消息:
+你已经看到了Java 5 **@Override**注释,它不是关键字,但是可以像使用关键字一样使用它。当你打算重写一个方法时,你可以选择添加这个注释,如果你不小心用了重载而不是重写,编译器会产生一个错误消息:
```java
// reuse/Lisa.java
@@ -1161,7 +1161,7 @@ public class Jurassic {
}
```
-**final** 类的属性可以根据个人选择是或不是 **final**。这同样适用于不管类是否是 **final** 的内部 **final** 属性。然而,由于 **final** 类禁止继承,类中所有的方法都被隐式地指定为 **final**,所以没有办法覆写它们。你可以在 final 类中的方法加上 **final** 修饰符,但不会增加任何意义。
+**final** 类的属性可以根据个人选择是或不是 **final**。同样,非 **final** 类的属性也可以根据个人选择是或不是 **final**。然而,由于 **final** 类禁止继承,类中所有的方法都被隐式地指定为 **final**,所以没有办法覆写它们。你可以在 final 类中的方法加上 **final** 修饰符,但不会增加任何意义。
### final 忠告
@@ -1169,9 +1169,9 @@ public class Jurassic {
但请留意你的假设。通常来说,预见一个类如何被复用是很困难的,特别是通用类。如果将一个方法指定为 **final**,可能会防止其他程序员的项目中通过继承来复用你的类,而这仅仅是因为你没有想到它被以那种方式使用。
-Java 标准类库就是一个很好的例子。尤其是 Java 1.0/1.1 的 **Vector** 类被广泛地使用,而且从效率考虑(这近乎是个幻想),如果它的所有方法没有被指定为 **final**,可能会更加有用。很容易想到,你可能会继承并覆写这么一个基础类,但是设计者们认为这么做不合适。有两个讽刺的原因。第一,**Stack** 继承自 **Vector**,就是说 **Stack** 是个 **Vector**,但从逻辑上来说不对。尽管如此,Java 设计者们仍然这么做,在用这种方式创建 **Stack** 时,他们应该意识到了 **final** 方法过于约束。
+Java 标准类库就是一个很好的例子。尤其是 Java 1.0/1.1 的 **Vector** 类被广泛地使用,如果它的所有方法没有因为从效率考虑(这近乎是个幻想),而被指定为 **final**,可能会更加有用。很容易想到,你可能会继承并覆写这么一个基础类,但是设计者们认为这么做不合适。有两个讽刺的原因。第一,**Stack** 继承自 **Vector**,就是说 **Stack** 是个 **Vector**,但从逻辑上来说不对。尽管如此,Java 设计者们仍然这么做,在用这种方式创建 **Stack** 时,他们应该意识到了 **final** 方法过于约束。
-第二,**Vector** 中的很多重要方法,比如 `addElement()` 和 `elementAt()` 方法都是同步的。在“并发编程”一章中会看同步会导致很大的执行开销,可能会抹煞 **final** 带来的好处。这加强了程序员永远无法正确猜到优化应该发生在何处的观点。如此笨拙的设计却出现在每个人都要使用的标准库中,太糟糕了。庆幸的是,现代 Java 容器用 **ArrayList** 代替了 **Vector**,它的行为要合理得多。不幸的是,仍然有很多新代码使用旧的集合类库,其中就包括 **Vector**。
+第二,**Vector** 中的很多重要方法,比如 `addElement()` 和 `elementAt()` 方法都是同步的。在“并发编程”一章中会看到同步会导致很大的执行开销,可能会抹煞 **final** 带来的好处。这加强了程序员永远无法正确猜到优化应该发生在何处的观点。如此笨拙的设计却出现在每个人都要使用的标准库中,太糟糕了。庆幸的是,现代 Java 容器用 **ArrayList** 代替了 **Vector**,它的行为要合理得多。不幸的是,仍然有很多新代码使用旧的集合类库,其中就包括 **Vector**。
Java 1.0/1.1 标准类库中另一个重要的类是 **Hashtable**(后来被 **HashMap** 取代),它不含任何 **final** 方法。本书中其他地方也提到,很明显不同的类是由不同的人设计的。**Hashtable** 就比 **Vector** 中的方法名简洁得多,这又是一条证据。对于类库的使用者来说,这是一个本不应该如此草率的事情。这种不规则的情况造成用户需要做更多的工作——这是对粗糙的设计和代码的又一讽刺。
@@ -1242,7 +1242,7 @@ j = 39
如果基类还存在自身的基类,那么第二个基类也将被加载,以此类推。接下来,根基类(例子中根基类是 **Insect**)的 **static** 的初始化开始执行,接着是派生类,以此类推。这点很重要,因为派生类中 **static** 的初始化可能依赖基类成员是否被正确地初始化。
-至此,必要的类都加载完毕,可以创建对象了。首先,对象中的所有基本类型变量都被置为默认值,对象引用被设为 **null** —— 这是通过将对象内存设为二进制零值一举生成的。接着会调用基类的构造器。本例中是自动调用的,但是你也可以使用 **super** 调用指定的基类构造器(在 **Beetle** 构造器中的第一步操作)。基类构造器和派生类构造器一样以相同的顺序经历相同的过程。当基类构造器完成后,实例变量按文本顺序初始化。最终,构造器的剩余部分被执行。
+至此,必要的类都加载完毕,对象可以被创建了。首先,对象中的所有基本类型变量都被置为默认值,对象引用被设为 **null** —— 这是通过将对象内存设为二进制零值一举生成的。接着会调用基类的构造器。本例中是自动调用的,但是你也可以使用 **super** 调用指定的基类构造器(在 **Beetle** 构造器中的第一步操作)。基类构造器和派生类构造器一样以相同的顺序经历相同的过程。当基类构造器完成后,实例变量按文本顺序初始化。最终,构造器的剩余部分被执行。
From d344d0d6bd73044506251931b40175634d6fcd07 Mon Sep 17 00:00:00 2001
From: salithfish <31979864+salithfish@users.noreply.github.com>
Date: Mon, 12 Oct 2020 11:46:02 +0800
Subject: [PATCH 31/68] =?UTF-8?q?=E4=BF=AE=E6=94=B924=E7=AB=A0=E5=B9=B6?=
=?UTF-8?q?=E5=8F=91=E7=BC=96=E7=A8=8B=E4=BB=A3=E7=A0=81=E9=97=AE=E9=A2=98?=
=?UTF-8?q?=20(#608)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
docs/book/24-Concurrent-Programming.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/book/24-Concurrent-Programming.md b/docs/book/24-Concurrent-Programming.md
index e8ed661e..201b9a3d 100755
--- a/docs/book/24-Concurrent-Programming.md
+++ b/docs/book/24-Concurrent-Programming.md
@@ -290,7 +290,7 @@ Java 8 CompletableFuture 是一个更好的解决方案:它允许你将操作
## 并行流
-Java 8 流的一个显著优点是,在某些情况下,它们可以很容易地并行化。这来自仔细的库设计,特别是流使用内部迭代的方式 - 也就是说,它们控制着自己的迭代器。特别是,他们使用一种特殊的迭代器,称为 Spliterator,它被限制为易于自动分割。我们只需要念 `.parallel()` 就会产生魔法般的结果,流中的所有内容都作为一组并行任务运行。如果你的代码是使用 Streams 编写的,那么并行化以提高速度似乎是一种琐事
+Java 8 流的一个显著优点是,在某些情况下,它们可以很容易地并行化。这来自库的仔细设计,特别是流使用内部迭代的方式 - 也就是说,它们控制着自己的迭代器。特别是,他们使用一种特殊的迭代器,称为 Spliterator,它被限制为易于自动分割。我们只需要念 `.parallel()` 就会产生魔法般的结果,流中的所有内容都作为一组并行任务运行。如果你的代码是使用 Streams 编写的,那么并行化以提高速度似乎是一种琐事
例如,考虑来自 Streams 的 Prime.java。查找质数可能是一个耗时的过程,我们可以看到该程序的计时:
@@ -615,7 +615,7 @@ public class ParallelStreamPuzzle {
}
}
public static void main(String[] args) {
- List x = Stream.generate(newIntGenerator())
+ List x = Stream.generate(new IntGenerator())
.limit(10)
.parallel() // [1]
.collect(Collectors.toList());
From 643b2a8d2a40baa16935a8379bebeb119212a309 Mon Sep 17 00:00:00 2001
From: Hao Lin <1184264181@qq.com>
Date: Tue, 20 Oct 2020 11:35:48 +0800
Subject: [PATCH 32/68] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BA=86finaly?=
=?UTF-8?q?=E7=9A=84=E9=94=99=E5=88=AB=E5=AD=97=20(#609)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
docs/book/15-Exceptions.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/book/15-Exceptions.md b/docs/book/15-Exceptions.md
index 3d2895fb..ecb6ff8f 100644
--- a/docs/book/15-Exceptions.md
+++ b/docs/book/15-Exceptions.md
@@ -1393,7 +1393,7 @@ StormyInning.walk() 不能通过编译是因为它抛出了一个 Inning.walk()
有一点很重要,即你要时刻询问自己“如果异常发生了,所有东西能被正确的清理吗?"尽管大多数情况下是非常安全的,但涉及构造器时,问题就出现了。构造器会把对象设置成安全的初始状态,但还会有别的动作,比如打开一个文件,这样的动作只有在对象使用完毕并且用户调用了特殊的清理方法之后才能得以清理。如果在构造器内抛出了异常,这些清理行为也许就不能正常工作了。这意味着在编写构造器时要格外细心。
-你也许会认为使用 finally 就可以解决问题。但问题并非如此简单,因为 finally 会每次都执行清理代码。如果构造器在其执行过程中半途而废,也许该对象的某些部分还没有被成功创建,而这些部分在 finaly 子句中却是要被清理的。
+你也许会认为使用 finally 就可以解决问题。但问题并非如此简单,因为 finally 会每次都执行清理代码。如果构造器在其执行过程中半途而废,也许该对象的某些部分还没有被成功创建,而这些部分在 finally 子句中却是要被清理的。
在下面的例子中,建立了一个 InputFile 类,它能打开一个文件并且每次读取其中的一行。这里使用了 Java 标准输入/输出库中的 FileReader 和 BufferedReader 类(将在 [附录:I/O 流 ](./Appendix-IO-Streams.md) 中讨论),这些类的基本用法很简单,你应该很容易明白:
From f4586b506004319bc5dded191e4b86c2a4504fd9 Mon Sep 17 00:00:00 2001
From: sleepingraven <32897701+sleepingraven@users.noreply.github.com>
Date: Tue, 27 Oct 2020 10:55:18 +0800
Subject: [PATCH 33/68] =?UTF-8?q?=E6=95=99=E5=AD=A6=E7=9B=AE=E6=A0=87=20(L?=
=?UTF-8?q?ingCoder#496)=20(#612)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* 半角括号、删除多余空格 (#494)
* 前言 (#496)
* 上传旧文档
* Revert "上传旧文档"
This reverts commit f053e7d36126ce530def85a61d4ab09ea0bc5210.
* 新文档
---
docs/book/00-Preface.md | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/docs/book/00-Preface.md b/docs/book/00-Preface.md
index 0e2ccbd0..94523a82 100644
--- a/docs/book/00-Preface.md
+++ b/docs/book/00-Preface.md
@@ -11,15 +11,15 @@
## 教学目标
-每章讲授一个或一组相关的概念,并且这些知识不依赖于尚未学习到的章节。如此,学习者可以在当前知识的背景框架下循序渐进地掌握 Java。
+每章讲授一个或一组相关的概念,并且不依赖于尚未介绍的特性。这样你就可以在现有的知识背景下,在继续向前学习之前,消化吸收每一部分内容。
本书的教学目标:
-1. 循序渐进地呈现学习内容,以便于你在不依赖后置知识框架的情况下轻松完成现有的学习任务,同时尽量保证前面章节的内容在后面的学习中得到运用。如果确有必要引入我们还没学习到的知识概念,我会做个简短地介绍。
+1. 循序渐进地呈现学习内容,使读者可以很容易地将每个知识点融会贯通;同时仔细地对特性的讲解进行排序,以使得你在看到对某个特性的运用之前,会先了解它。如果确有必要引入还未学习的知识概念,我会做个简短的介绍。
-2. 尽可能地使用简单和简短的示例,方便读者理解。而不强求引入解决实际问题的例子。因为我发现,相比解决某个实际问题,读者更乐于看到自己真正理解了示例的每个细节。或许我会因为这些“玩具示例”而被一些人所诟病,但我更愿意相信这样的教学方式更加有效。
+2. 使用尽可能简单和简短的示例,方便读者理解。而不强求引入解决“现实世界”中问题的例子。因为我发现,通常初学者更乐于看到自己通晓示例的每个细节,而非明晰所解决的问题范畴。或许我会因这些“玩具示例”而被一些人所诟病,但是我乐意接受那些有利于为教育带来益处的种种事物,更希望读者们能因此保持饶有兴趣地学习。
-3. 把我知道以及我认为对于你学习语言很重要的东西都告诉你。我认为信息的重要性是分层次结构的。绝大多数情况下,我们没必要弄清问题的所有本质。好比编程语言中的某些特性和实现细节,95% 的程序员都不需要去知道。这些细节除了会加重你的学习成本,还让你更觉得这门语言好复杂。如果你非要考虑这些细节,那么它还会迷惑该代码的阅读者/维护者,所以我主张选择简单的方法解决问题。
+3. 向读者提供“我认为对理解这种程序设计语言来说很重要”的部分,而不是提供我所知道的所有事情。我认为信息的重要性是分层次结构的。绝大多数情况下,我们没必要弄清问题的所有本质。好比编程语言中的某些特性和实现细节,95% 的程序员都不需要去知道。这些细节除了会加重你的学习成本,还让你更觉得这门语言好复杂。如果你非要考虑这些细节,那么它还会迷惑该代码的阅读者/维护者,所以我主张选择简单的方法解决问题。
4. 希望本书能为你打下坚实的基础,方便你将来学习更难的课程和书籍。
From 4d21726c4a93e104b410d06668c73975ba4069b5 Mon Sep 17 00:00:00 2001
From: Hao Lin <1184264181@qq.com>
Date: Wed, 4 Nov 2020 12:08:43 +0800
Subject: [PATCH 34/68] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BA=86=E9=94=99?=
=?UTF-8?q?=E5=88=AB=E5=AD=97=20(#614)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* 修复了finaly的错别字
* 修复Mao的错别字,实际应为Map
* 修复‘既’的错别字
---
docs/book/20-Generics.md | 2 +-
docs/book/Appendix-Collection-Topics.md | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/book/20-Generics.md b/docs/book/20-Generics.md
index 43bb33ba..72263fcc 100644
--- a/docs/book/20-Generics.md
+++ b/docs/book/20-Generics.md
@@ -3537,7 +3537,7 @@ NeedCasting.java:10: warning: [unchecked] unchecked cast
1 warning
```
-你会被强制要求转型,但是又被告知不应该转型。为了解决这个问题,必须使用 Java 5 引入的新的转型形式,既通过泛型类来转型:
+你会被强制要求转型,但是又被告知不应该转型。为了解决这个问题,必须使用 Java 5 引入的新的转型形式,即通过泛型类来转型:
```java
// generics/ClassCasting.java
diff --git a/docs/book/Appendix-Collection-Topics.md b/docs/book/Appendix-Collection-Topics.md
index 511de489..083462a7 100644
--- a/docs/book/Appendix-Collection-Topics.md
+++ b/docs/book/Appendix-Collection-Topics.md
@@ -2324,7 +2324,7 @@ dancing
| **LinkedHashMap** | 与 **HashMap** 类似,但是当遍历时,可以按插入顺序或最近最少使用(LRU)顺序获取键值对。只比 **HashMap** 略慢,一个例外是在迭代时,由于其使用链表维护内部顺序,所以会更快些。 |
| **TreeMap** | 基于红黑树的实现。当查看键或键值对时,它们按排序顺序(由 **Comparable** 或 **Comparator** 确定)。 **TreeMap** 的侧重点是按排序顺序获得结果。 **TreeMap** 是唯一使用 `subMap()` 方法的 **Map** ,它返回红黑树的一部分。 |
| **WeakHashMap** | 一种具有 *弱键*(weak keys) 的 **Map** ,为了解决某些类型的问题,它允许释放 **Map** 所引用的对象。如果在 **Map** 外没有对特定键的引用,则可以对该键进行垃圾回收。 |
-| **ConcurrentHashMap** | 不使用同步锁定的线程安全 **Mao** 。这在[第二十四章 并发编程]() 一章中讨论。 |
+| **ConcurrentHashMap** | 不使用同步锁定的线程安全 **Map** 。这在[第二十四章 并发编程]() 一章中讨论。 |
| **IdentityHashMap** | 使用 `==` 而不是 `equals()` 来比较键。仅用于解决特殊问题,不适用于一般用途。 |
散列是在 **Map** 中存储元素的最常用方法。
From 0a4365eed12605e63679d960bea38b61133f1728 Mon Sep 17 00:00:00 2001
From: Hao Lin <1184264181@qq.com>
Date: Fri, 13 Nov 2020 15:03:06 +0800
Subject: [PATCH 35/68] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=A1=A8=E6=A0=BC?=
=?UTF-8?q?=E4=B8=AD=E5=88=86=E8=A1=8C=E6=97=B6=E7=9A=84=E6=AF=8F=E8=A1=8C?=
=?UTF-8?q?=E5=88=86=E5=8F=B7=E6=97=B6=E6=9C=89=E6=97=B6=E6=97=A0=E7=9A=84?=
=?UTF-8?q?=E9=97=AE=E9=A2=98=20(#617)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* 修复了finaly的错别字
* 修复Mao的错别字,实际应为Map
* 修复‘既’的错别字
* 统一风格
---
docs/book/23-Annotations.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/book/23-Annotations.md b/docs/book/23-Annotations.md
index 1b585691..af5fb8dc 100644
--- a/docs/book/23-Annotations.md
+++ b/docs/book/23-Annotations.md
@@ -117,8 +117,8 @@ Java 语言中目前有 5 种标准注解(前面介绍过),以及 5 种元
| 注解 | 解释 |
| ----------- | ------------------------------------------------------------ |
-| @Target | 表示注解可以用于哪些地方。可能的 **ElementType** 参数包括:
**CONSTRUCTOR**:构造器的声明
**FIELD**:字段声明(包括 enum 实例)
**LOCAL_VARIABLE**:局部变量声明
**METHOD**:方法声明
**PACKAGE**:包声明
**PARAMETER**:参数声明
**TYPE**:类、接口(包括注解类型)或者 enum 声明 |
-| @Retention | 表示注解信息保存的时长。可选的 **RetentionPolicy** 参数包括:
**SOURCE**:注解将被编译器丢弃
**CLASS**:注解在 class 文件中可用,但是会被 VM 丢弃。
**RUNTIME**:VM 将在运行期也保留注解,因此可以通过反射机制读取注解的信息。 |
+| @Target | 表示注解可以用于哪些地方。可能的 **ElementType** 参数包括:
**CONSTRUCTOR**:构造器的声明;
**FIELD**:字段声明(包括 enum 实例);
**LOCAL_VARIABLE**:局部变量声明;
**METHOD**:方法声明;
**PACKAGE**:包声明;
**PARAMETER**:参数声明;
**TYPE**:类、接口(包括注解类型)或者 enum 声明。 |
+| @Retention | 表示注解信息保存的时长。可选的 **RetentionPolicy** 参数包括:
**SOURCE**:注解将被编译器丢弃;
**CLASS**:注解在 class 文件中可用,但是会被 VM 丢弃;
**RUNTIME**:VM 将在运行期也保留注解,因此可以通过反射机制读取注解的信息。 |
| @Documented | 将此注解保存在 Javadoc 中 |
| @Inherited | 允许子类继承父类的注解 |
| @Repeatable | 允许一个注解可以被使用一次或者多次(Java 8)。 |
From ad9de0d3871852b0466c427201258cb1411e9f69 Mon Sep 17 00:00:00 2001
From: Joe <736777445@qq.com>
Date: Fri, 20 Nov 2020 10:57:22 +0800
Subject: [PATCH 36/68] Update README.md
---
docs/README.md | 4 ----
1 file changed, 4 deletions(-)
diff --git a/docs/README.md b/docs/README.md
index 328b1fe4..fca2f067 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -38,10 +38,6 @@
本项目基于 MIT 协议开源。
-## 友情链接
-
-Effective Java 第 3 版: https://github.com/sjsdfg/effective-java-3rd-chinese
-
## 联系方式
- E-mail :
From 11a6ac3969c265a8648588da62da1a4bf0c462c3 Mon Sep 17 00:00:00 2001
From: andyphone <792998301@qq.com>
Date: Tue, 24 Nov 2020 18:30:16 +0800
Subject: [PATCH 37/68] =?UTF-8?q?=E7=BA=A0=E9=94=99=20(#618)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* 1
* 2
* 没有第三种形式吧?
---
docs/book/06-Housekeeping.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/book/06-Housekeeping.md b/docs/book/06-Housekeeping.md
index 0a7a5f1c..0248808c 100644
--- a/docs/book/06-Housekeeping.md
+++ b/docs/book/06-Housekeeping.md
@@ -1379,7 +1379,7 @@ public class ArrayInit {
在这两种形式中,初始化列表的最后一个逗号是可选的(这一特性使维护长列表变得更容易)。
-尽管第一种形式很有用,但是它更加受限,因为它只能用于数组定义处。第二种和第三种形式可以用在任何地方,甚至用在方法的内部。例如,你创建了一个 **String** 数组,将其传递给另一个类的 `main()` 方法,如下:
+尽管第一种形式很有用,但是它更加受限,因为它只能用于数组定义处。第二种形式可以用在任何地方,甚至用在方法的内部。例如,你创建了一个 **String** 数组,将其传递给另一个类的 `main()` 方法,如下:
```java
// housekeeping/DynamicArray.java
From 2dfca3c1da67af80179a7a64a4f848ee8461a4c5 Mon Sep 17 00:00:00 2001
From: witcxc
Date: Wed, 25 Nov 2020 11:08:21 +0800
Subject: [PATCH 38/68] =?UTF-8?q?=E5=B0=86=E9=98=9F=E5=88=97=E8=A1=A8?=
=?UTF-8?q?=E8=BF=B0=E5=BE=97=E6=9B=B4=E6=B8=85=E6=99=B0=20(#619)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: happyleaf.cx
---
docs/book/16-Validating-Your-Code.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/book/16-Validating-Your-Code.md b/docs/book/16-Validating-Your-Code.md
index 940ba5a2..26917eab 100644
--- a/docs/book/16-Validating-Your-Code.md
+++ b/docs/book/16-Validating-Your-Code.md
@@ -555,7 +555,7 @@ assert invariant();
}
```
-**in** 计数器指示数组中下一个对象所在的位置。**out** 计数器指示下一个对象来自何处。**wrapped** 的flag表示 **in** 已经“绕着圆圈”走了,现在从后面出来了。当**in**和 **out** 重合时,队列为空(如果包装为 **false** )或满(如果 **wrapped** 为 **true** )。
+**in** 计数器指示数组中下一个入队对象所在的位置。**out** 计数器指示下一个出队对象来自何处。**wrapped** 的flag表示入队和出队指针顺序是否变换, 为**false** 表示**in**在**out**之前,为**true**则顺序相反。当**in**和 **out** 重合时,队列为空(如果**wrapped**为 **false** )或满(如果 **wrapped** 为 **true** )。
**put()** 和 **get()** 方法调用 **precondition()** ,**postcondition()**, 和 **invariant**(),这些都是在类中定义的私有方法。前置**precondition()** 和 **postcondition()** 是用来阐明代码的辅助方法。
From 9dacdce2b9edfe58b1b149b02e7adac2b2d8cb7d Mon Sep 17 00:00:00 2001
From: andyphone <792998301@qq.com>
Date: Thu, 26 Nov 2020 14:19:35 +0800
Subject: [PATCH 39/68] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AF=AD=E5=8F=A5?=
=?UTF-8?q?=E6=8B=97=E5=8F=A3=E9=97=AE=E9=A2=98=20(#622)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* 1
* 2
* 没有第三种形式吧?
* 修改语句拗口问题
* 修改语句拗口问题 2
* 修改语句拗口问题 3
* 修改语句拗口问题 4
---
docs/book/08-Reuse.md | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/docs/book/08-Reuse.md b/docs/book/08-Reuse.md
index 824d59b9..729d4ca3 100644
--- a/docs/book/08-Reuse.md
+++ b/docs/book/08-Reuse.md
@@ -68,7 +68,7 @@ i = 0 f = 0.0 source = Constructed
```
-这两个类中定义的一个方法是特殊的: `toString()`。每个非基本类型对象都有一个 `toString()` 方法,在编译器需要字符串但它有对象的特殊情况下调用该方法。因此,在 [1] 中,编译器看到你试图“添加”一个 **WaterSource** 类型的字符串对象 。因为字符串只能拼接另一个字符串,所以它就先会调用 `toString()` 将 **source** 转换成一个字符串。然后,它可以拼接这两个字符串并将结果字符串传递给 `System.out.println()`。要对创建的任何类允许这种行为,只需要编写一个 **toString()** 方法。在 `toString()` 上使用 **@Override** 注释来告诉编译器,以确保正确地覆盖。**@Override** 是可选的,但它有助于验证你没有拼写错误 (或者更微妙地说,大小写字母输入错误)。类中的基本类型字段自动初始化为零,正如 **object Everywhere** 一章中所述。但是对象引用被初始化为 **null**,如果你尝试调用其任何一个方法,你将得到一个异常(一个运行时错误)。方便的是,打印 **null** 引用却不会得到异常。
+这两个类中定义的一个方法是特殊的: `toString()`。每个非基本类型对象都有一个 `toString()` 方法,在编译器需要字符串但它有对象的特殊情况下调用该方法。因此,在 [1] 中,编译器看到你试图“添加”一个 **WaterSource** 类型的字符串对象 。因为字符串只能拼接另一个字符串,所以它就先会调用 `toString()` 将 **source** 转换成一个字符串。然后,它可以拼接这两个字符串并将结果字符串传递给 `System.out.println()`。要对创建的任何类允许这种行为,只需要编写一个 **toString()** 方法。在 `toString()` 上使用 **@Override** 注解来告诉编译器,以确保正确地覆盖。**@Override** 是可选的,但它有助于验证你没有拼写错误 (或者更微妙地说,大小写字母输入错误)。类中的基本类型字段自动初始化为零,正如 **object Everywhere** 一章中所述。但是对象引用被初始化为 **null**,如果你尝试调用其任何一个方法,你将得到一个异常(一个运行时错误)。方便的是,打印 **null** 引用却不会得到异常。
编译器不会为每个引用创建一个默认对象,这是有意义的,因为在许多情况下,这会导致不必要的开销。初始化引用有四种方法:
@@ -690,9 +690,10 @@ doh(Milhouse)
````
-**Homer** 的所有重载方法在 **Bart** 中都是可用的,尽管 **Bart** 引入了一种新的重载方法。在下一章中你将看到,使用与基类中完全相同的签名和返回类型覆盖相同名称的方法要常见得多。否则就会令人困惑。
+**Homer** 的所有重载方法在 **Bart** 中都是可用的,尽管 **Bart** 引入了一种新的重载方法。正如你将在下一章中看到的那样,比起重载,更常见的是覆盖同名方法,使用与基类中完全相同的方法签名[^1]和返回类型。否则会让人感到困惑。
+
+你已经看到了Java 5 **@Override**注解,它不是关键字,但是可以像使用关键字一样使用它。当你打算重写一个方法[^2]时,你可以选择添加这个注解,如果你不小心用了重载而不是重写,编译器会产生一个错误消息:
-你已经看到了Java 5 **@Override**注释,它不是关键字,但是可以像使用关键字一样使用它。当你打算重写一个方法时,你可以选择添加这个注释,如果你不小心用了重载而不是重写,编译器会产生一个错误消息:
```java
// reuse/Lisa.java
@@ -709,8 +710,14 @@ class Lisa extends Homer {
```
-**{WillNotCompile}** 标记将该文件排除在本书的 **Gradle** 构建之外,但是如果你手工编译它,你将看到:方法不会覆盖超类中的方法, **@Override** 注释防止你意外地重载。
+**{WillNotCompile}** 标记将该文件排除在本书的 **Gradle** 构建之外,但是如果你手工编译它,你将看到:method does not override a method from its superclass.方法不会重写超类中的方法, **@Override** 注解能防止你意外地重载。
+
+- **[1]** 方法签名——方法名和参数类型的合称
+
+- **[2]** 重写——覆盖同名方法,使用与基类中完全相同的方法签名和返回类型[^3]
+- **[3]** 在java 1.4版本以前,重写方法的返回值类型被要求必须与被重写方法一致,但是在java 5.0中放宽了这一个限制,添加了对协变返回类型的支持,在重写的时候,重写方法的返回值类型可以是被重写方法返回值类型的子类。
+
## 组合与继承的选择
From df95e50ae7668e79ece0a9be4e9d661841b679e8 Mon Sep 17 00:00:00 2001
From: andyphone <792998301@qq.com>
Date: Thu, 26 Nov 2020 21:09:37 +0800
Subject: [PATCH 40/68] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AF=AD=E5=8F=A5?=
=?UTF-8?q?=E6=8B=97=E5=8F=A3=E9=97=AE=E9=A2=98=20(#623)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* 1
* 2
* 没有第三种形式吧?
* 修改语句拗口问题
* 修改语句拗口问题 2
* 修改语句拗口问题 3
* 修改语句拗口问题 4
* 修改语句拗口问题 5
---
docs/book/08-Reuse.md | 4 +++-
docs/book/10-Interfaces.md | 2 +-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/docs/book/08-Reuse.md b/docs/book/08-Reuse.md
index 729d4ca3..e10f8751 100644
--- a/docs/book/08-Reuse.md
+++ b/docs/book/08-Reuse.md
@@ -1176,12 +1176,14 @@ public class Jurassic {
但请留意你的假设。通常来说,预见一个类如何被复用是很困难的,特别是通用类。如果将一个方法指定为 **final**,可能会防止其他程序员的项目中通过继承来复用你的类,而这仅仅是因为你没有想到它被以那种方式使用。
-Java 标准类库就是一个很好的例子。尤其是 Java 1.0/1.1 的 **Vector** 类被广泛地使用,如果它的所有方法没有因为从效率考虑(这近乎是个幻想),而被指定为 **final**,可能会更加有用。很容易想到,你可能会继承并覆写这么一个基础类,但是设计者们认为这么做不合适。有两个讽刺的原因。第一,**Stack** 继承自 **Vector**,就是说 **Stack** 是个 **Vector**,但从逻辑上来说不对。尽管如此,Java 设计者们仍然这么做,在用这种方式创建 **Stack** 时,他们应该意识到了 **final** 方法过于约束。
+Java 标准类库就是一个很好的例子。尤其是 Java 1.0/1.1 的 **Vector** 类被广泛地使用,然而它的所有方法出于"效率"考虑(然而并没有提升效率,只是幻觉)全被指定为 **final** ,如果不指定 **final** 的话,可能会更加有用[^1]。很容易想到,你可能会继承并覆写这么一个基础类,但是设计者们认为这么做不合适。有两个讽刺的原因。第一,**Stack** 继承自 **Vector**,就是说 **Stack** 是个 **Vector**,但从逻辑上来说不对。尽管如此,Java 设计者们仍然这么做,在用这种方式创建 **Stack** 时,他们应该意识到了 **final** 方法过于约束。
第二,**Vector** 中的很多重要方法,比如 `addElement()` 和 `elementAt()` 方法都是同步的。在“并发编程”一章中会看到同步会导致很大的执行开销,可能会抹煞 **final** 带来的好处。这加强了程序员永远无法正确猜到优化应该发生在何处的观点。如此笨拙的设计却出现在每个人都要使用的标准库中,太糟糕了。庆幸的是,现代 Java 容器用 **ArrayList** 代替了 **Vector**,它的行为要合理得多。不幸的是,仍然有很多新代码使用旧的集合类库,其中就包括 **Vector**。
Java 1.0/1.1 标准类库中另一个重要的类是 **Hashtable**(后来被 **HashMap** 取代),它不含任何 **final** 方法。本书中其他地方也提到,很明显不同的类是由不同的人设计的。**Hashtable** 就比 **Vector** 中的方法名简洁得多,这又是一条证据。对于类库的使用者来说,这是一个本不应该如此草率的事情。这种不规则的情况造成用户需要做更多的工作——这是对粗糙的设计和代码的又一讽刺。
+- **[1]** Java 1.4 开始已将 **Vector** 类大多数方法的 **final** 去掉
+
## 类初始化和加载
diff --git a/docs/book/10-Interfaces.md b/docs/book/10-Interfaces.md
index f2bc527e..7eb5cf49 100644
--- a/docs/book/10-Interfaces.md
+++ b/docs/book/10-Interfaces.md
@@ -104,7 +104,7 @@ public class Instantiable extends Uninstantiable {
}
```
-留意 `@Override` 的使用。没有这个注解的话,如果你没有定义相同的方法名或签名,抽象机制会认为你没有实现抽象方法从而产生编译时错误。因此,你可能认为这里的 `@Override` 是多余的。但是,`@Override` 还提示了这个方法被覆写——我认为这是有用的,所以我会使用 `@Override`,即使在没有这个注解,编译器告诉我错误的时候。
+留意 `@Override` 的使用。没有这个注解的话,如果你没有定义相同的方法名或签名,抽象机制会认为你没有实现抽象方法从而产生编译时错误。因此,你可能认为这里的 `@Override` 是多余的。但是,`@Override` 还提示了这个方法被覆写——我认为这是有用的,所以我会使用 `@Override`,不仅仅是因为当没有这个注解时,编译器会告诉我出错。
记住,事实上的访问权限是“friendly”。你很快会看到接口自动将其方法指明为 **public**。事实上,接口只允许 **public** 方法,如果不加访问修饰符的话,接口的方法不是 **friendly** 而是 **public**。然而,抽象类允许每件事:
From a9bda4acfd44456bccbe938166688caa9be21a0b Mon Sep 17 00:00:00 2001
From: andyphone <792998301@qq.com>
Date: Fri, 27 Nov 2020 22:46:08 +0800
Subject: [PATCH 41/68] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AF=AD=E5=8F=A5?=
=?UTF-8?q?=E6=8B=97=E5=8F=A3=E9=97=AE=E9=A2=98=20(#624)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* 1
* 2
* 没有第三种形式吧?
* 修改语句拗口问题
* 修改语句拗口问题 2
* 修改语句拗口问题 3
* 修改语句拗口问题 4
* 修改语句拗口问题 5
* 修改语句拗口问题 6
* 修改语句拗口问题 7
* 修改语句拗口问题 8
* 修改语句拗口问题 9
---
docs/book/09-Polymorphism.md | 4 ++--
docs/book/10-Interfaces.md | 8 ++++----
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/docs/book/09-Polymorphism.md b/docs/book/09-Polymorphism.md
index 63075630..ddca482d 100644
--- a/docs/book/09-Polymorphism.md
+++ b/docs/book/09-Polymorphism.md
@@ -964,7 +964,7 @@ Disposing Shared 0
**static long counter** 跟踪所创建的 **Shared** 实例数量,还提供了 **id** 的值。**counter** 的类型是 **long** 而不是 **int**,以防溢出(这只是个良好实践,对于本书的所有示例,**counter** 不会溢出)。**id** 是 **final** 的,因为它的值在初始化时确定后不应该变化。
-在将一个 **shared** 对象附着在类上时,必须记住调用 `addRef()`,而 `dispose()` 方法会跟踪引用数,以确定在何时真正地执行清理工作。使用这种技巧需要加倍细心,但是如果正在共享需要被清理的对象,就没有太多选择了。
+在将一个 **shared** 对象附着在类上时,必须记住调用 `addRef()`,而 `dispose()` 方法会跟踪引用数,以确定在何时真正地执行清理工作。使用这种技巧需要加倍细心,但是如果需要清理正在共享的对象,你没有太多选择。
### 构造器内部多态方法的行为
@@ -1154,7 +1154,7 @@ HappyActor
SadActor
```
-**Stage** 对象中包含了 **Actor** 引用,该引用被初始化为指向一个 **HappyActor** 对象,这意味着 `performPlay()` 会产生一个特殊行为。但是既然引用可以在运行时与其他不同的对象绑定,那么它就可以被替换成对 **SadActor** 的引用,`performPlay()` 的行为随之改变。这样你就获得了运行时的动态灵活性(这被称为状态模式)。与之相反,我们不能在运行时决定继承不同的对象,那在编译时就完全确定下来了。
+**Stage** 对象中包含了 **Actor** 引用,该引用被初始化为指向一个 **HappyActor** 对象,这意味着 `performPlay()` 会产生一个特殊行为。但是既然引用可以在运行时与其他不同的对象绑定,那么它就可以被替换成对 **SadActor** 的引用,`performPlay()` 的行为随之改变。这样你就获得了运行时的动态灵活性(这被称为状态模式)。与之相反,我们无法在运行时才决定继承不同的对象;那在编译时就完全决定好了。
有一条通用准则:使用继承表达行为的差异,使用属性表达状态的变化。在上个例子中,两者都用到了。通过继承得到的两个不同类在 `act()` 方法中表达了不同的行为,**Stage** 通过组合使自己的状态发生变化。这里状态的改变产生了行为的改变。
diff --git a/docs/book/10-Interfaces.md b/docs/book/10-Interfaces.md
index 7eb5cf49..b7cf5cb5 100644
--- a/docs/book/10-Interfaces.md
+++ b/docs/book/10-Interfaces.md
@@ -602,7 +602,7 @@ public interface Operations {
}
```
-这是模版方法设计模式的一个版本(在“设计模式”一章中详细描述),`runOps()` 是一个模版方法。`runOps()` 使用可变参数列表,因而我们可以传入任意多的 **Operation** 参数并按顺序运行它们:
+这是*模版*方法设计模式的一个版本(在“设计模式”一章中详细描述),`runOps()` 是一个模版方法。`runOps()` 使用可变参数列表,因而我们可以传入任意多的 **Operation** 参数并按顺序运行它们:
```java
// interface/Machine.java
@@ -768,17 +768,17 @@ Woodwind.play() MIDDLE_C
| 状态 | 不能包含属性(除了静态属性,不支持对象状态) | 可以包含属性,非抽象方法可能引用这些属性 |
| 默认方法 和 抽象方法 | 不需要在子类中实现默认方法。默认方法可以引用其他接口的方法 | 必须在子类中实现抽象方法 |
| 构造器 | 没有构造器 | 可以有构造器 |
-| 可见性 | 隐式 **public** | 可以是 **protected** 或友元 |
+| 可见性 | 隐式 **public** | 可以是 **protected** 或 "friendly" |
抽象类仍然是一个类,在创建新类时只能继承它一个。而创建类的过程中可以实现多个接口。
-有一条实际经验:尽可能地抽象。因此,更倾向使用接口而不是抽象类。只有当必要时才使用抽象类。除非必须使用,否则不要用接口和抽象类。大多数时候,普通类已经做得很好,如果不行的话,再移动到接口或抽象类中。
+有一条实际经验:在合理的范围内尽可能地抽象。因此,更倾向使用接口而不是抽象类。只有当必要时才使用抽象类。除非必须使用,否则不要用接口和抽象类。大多数时候,普通类已经做得很好,如果不行的话,再移动到接口或抽象类中。
## 完全解耦
-当方法操纵的是一个类而非接口时,它就只能作用于那个类或其子类。如果想把方法应用于那个继承层级结构之外的类,就会触霉头。接口在很大程度上放宽了这个限制,因而使用接口可以编写复用性更好的代码。
+每当一个方法与一个类而不是接口一起工作时(当方法的参数是类而不是接口),你只能应用那个类或它的子类。如果你想把这方法应用到一个继承层次之外的类,是做不到的。接口在很大程度上放宽了这个限制,因而使用接口可以编写复用性更好的代码。
例如有一个类 **Processor** 有两个方法 `name()` 和 `process()`。`process()` 方法接受输入,修改并输出。把这个类作为基类用来创建各种不同类型的 **Processor**。下例中,**Processor** 的各个子类修改 String 对象(注意,返回类型可能是协变类型而非参数类型):
From 3708ab32f5c9b985a00e44c4f5e0c2518f98d2b5 Mon Sep 17 00:00:00 2001
From: andyphone <792998301@qq.com>
Date: Tue, 1 Dec 2020 12:55:39 +0800
Subject: [PATCH 42/68] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AF=AD=E5=8F=A5?=
=?UTF-8?q?=E6=8B=97=E5=8F=A3=E9=97=AE=E9=A2=98=20(#625)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* 1
* 2
* 没有第三种形式吧?
* 修改语句拗口问题
* 修改语句拗口问题 2
* 修改语句拗口问题 3
* 修改语句拗口问题 4
* 修改语句拗口问题 5
* 修改语句拗口问题 6
* 修改语句拗口问题 7
* 修改语句拗口问题 8
* 修改语句拗口问题 9
* 拗口问题
* 修改语句拗口问题 10
* 修改语句拗口问题 11
---
docs/book/10-Interfaces.md | 4 +++-
docs/book/11-Inner-Classes.md | 41 ++++++++++++++++++-----------------
2 files changed, 24 insertions(+), 21 deletions(-)
diff --git a/docs/book/10-Interfaces.md b/docs/book/10-Interfaces.md
index b7cf5cb5..f2257f52 100644
--- a/docs/book/10-Interfaces.md
+++ b/docs/book/10-Interfaces.md
@@ -602,7 +602,9 @@ public interface Operations {
}
```
-这是*模版*方法设计模式的一个版本(在“设计模式”一章中详细描述),`runOps()` 是一个模版方法。`runOps()` 使用可变参数列表,因而我们可以传入任意多的 **Operation** 参数并按顺序运行它们:
+
+这是*模板方法*设计模式的一个版本(在“设计模式”一章中详细描述),`runOps()` 是一个模板方法。`runOps()` 使用可变参数列表,因而我们可以传入任意多的 **Operation** 参数并按顺序运行它们:
+
```java
// interface/Machine.java
diff --git a/docs/book/11-Inner-Classes.md b/docs/book/11-Inner-Classes.md
index ea329e45..83376eb8 100755
--- a/docs/book/11-Inner-Classes.md
+++ b/docs/book/11-Inner-Classes.md
@@ -8,7 +8,7 @@
内部类是一种非常有用的特性,因为它允许你把一些逻辑相关的类组织在一起,并控制位于内部的类的可见性。然而必须要了解,内部类与组合是完全不同的概念,这一点很重要。在最初,内部类看起来就像是一种代码隐藏机制:将类置于其他类的内部。但是,你将会了解到,内部类远不止如此,它了解外部类,并能与之通信,而且你用内部类写出的代码更加优雅而清晰,尽管并不总是这样(而且 Java 8 的 Lambda 表达式和方法引用减少了编写内部类的需求)。
-最初,内部类可能看起来有些奇怪,而且要花些时间才能在设计中轻松地使用它们。对内部类的需求并非总是很明显的,但是在描述完内部类的基本语法与语义之后,"Why inner classes?"就应该使得内部类的益处明确显现了。
+最初,内部类可能看起来有些奇怪,而且要花些时间才能在设计中轻松地使用它们。对内部类的需求并非总是很明显的,但是在描述完内部类的基本语法与语义之后,就能明白使用内部类的好处了。
本章剩余部分包含了对内部类语法更加详尽的探索,这些特性是为了语言的完备性而设计的,但是你也许不需要使用它们,至少一开始不需要。因此,本章最初的部分也许就是你现在所需的全部,你可以将更详尽的探索当作参考资料。
@@ -170,7 +170,7 @@ public class Sequence {
0 1 2 3 4 5 6 7 8 9
```
-**Sequence** 类只是一个固定大小的 **Object** 的数组,以类的形式包装了起来。可以调用 `add()` 在序列末尾增加新的 **Object**(只要还有空间),要获取 **Sequence** 中的每一个对象,可以使用 **Selector** 接口。这是“迭代器”设计模式的一个例子,在本书稍后的部分将更多地学习它。**Selector** 允许你检查序列是否到末尾了(`end()`),访问当前对象(`current()`),以及移到序列中的下一个对象(`next()`)。因为 **Selector** 是一个接口,所以别的类可以按它们自己的方式来实现这个接口,并且其他方法能以此接口为参数,来生成更加通用的代码。
+**Sequence** 类只是一个固定大小的 **Object** 的数组,以类的形式包装了起来。可以调用 `add()` 在序列末尾增加新的 **Object**(只要还有空间),要获取 **Sequence** 中的每一个对象,可以使用 **Selector** 接口。这是“*迭代器*”设计模式的一个例子,在本书稍后的部分将更多地学习它。**Selector** 允许你检查序列是否到末尾了(`end()`),访问当前对象(`current()`),以及移到序列中的下一个对象(`next()`)。因为 **Selector** 是一个接口,所以别的类可以按它们自己的方式来实现这个接口,并且其他方法能以此接口为参数,来生成更加通用的代码。
这里,**SequenceSelector** 是提供 **Selector** 功能的 **private** 类。可以看到,在 `main()` 中创建了一个 **Sequence**,并向其中添加了一些 **String** 对象。然后通过调用 `selector()` 获取一个 **Selector**,并用它在 **Sequence** 中移动和选择每一个元素。
最初看到 **SequenceSelector**,可能会觉得它只不过是另一个内部类罢了。但请仔细观察它,注意方法 `end()`,`current()` 和 `next()` 都用到了 **items**,这是一个引用,它并不是 **SequenceSelector** 的一部分,而是外部类中的一个 **private** 字段。然而内部类可以访问其外部类的方法和字段,就像自己拥有它们似的,这带来了很大的方便,就如前面的例子所示。
@@ -325,7 +325,7 @@ public class TestParcel {
## 内部类方法和作用域
-到目前为止,读者所看到的只是内部类的典型用途。通常,如果所读、写的代码包含了内部类,那么它们都是“平凡的”内部类,简单并且容易理解。然而,内部类的语法覆盖了大量其他的更加难以理解的技术。例如,可以在一个方法里面或者在任意的作用域内定义内部类。
+到目前为止,读者所看到的只是内部类的典型用途。通常,如果所读、写的代码包含了内部类,那么它们都是“平凡的”内部类,简单并且容易理解。然而,内部类的语法重写了大量其他的更加难以理解的技术。例如,可以在一个方法里面或者在任意的作用域内定义内部类。
这么做有两个理由:
@@ -513,7 +513,7 @@ public class Parcel9 {
}
```
-如果定义一个匿名内部类,并且希望它使用一个在其外部定义的对象,那么编译器会要求其参数引用是 **final** 的(也就是说,它在初始化后不会改变,所以可以被当作 **final**),就像你在 `destination()` 的参数中看到的那样。这里省略掉 **final** 也没问题,但是通常最好加上 **final** 作为一种暗示。
+如果在定义一个匿名内部类时,它要使用一个外部环境(在本匿名内部类之外定义)对象,那么编译器会要求其(该对象)参数引用是 **final** 或者是 “effectively final”(也就是说,该参数在初始化后不能被重新赋值,所以可以当作 **final**)的,就像你在 `destination()` 的参数中看到的那样。这里省略掉 **final** 也没问题,但通常加上 **final** 作为提醒比较好。
如果只是简单地给一个字段赋值,那么此例中的方法是很好的。但是,如果想做一些类似构造器的行为,该怎么办呢?在匿名类中不可能有命名构造器(因为它根本没名字!),但通过实例初始化,就能够达到为匿名内部类创建一个构造器的效果,就像这样:
@@ -552,7 +552,7 @@ Inside instance initializer
In anonymous f()
```
-在此例中,不要求变量一定是 **final** 的。因为被传递给匿名类的基类的构造器,它并不会在匿名类内部被直接使用。
+在此例中,不要求变量 **i** 一定是 **final** 的。因为 **i** 被传递给匿名类的基类的构造器,它并不会在匿名类内部被直接使用。
下例是带实例初始化的"parcel"形式。注意 `destination()` 的参数必须是 **final** 的,因为它们是在匿名类内部使用的(译者注:即使不加 **final**, Java 8 的编译器也会为我们自动加上 **final**,以保证数据的一致性)。
@@ -591,15 +591,15 @@ Over budget!
在实例初始化操作的内部,可以看到有一段代码,它们不能作为字段初始化动作的一部分来执行(就是 **if** 语句)。所以对于匿名类而言,实例初始化的实际效果就是构造器。当然它受到了限制-你不能重载实例初始化方法,所以你仅有一个这样的构造器。
-匿名内部类与正规的继承相比有些受限,因为匿名内部类既可以扩展类,也可以实现接口,但是不能两者兼备。而且如果是实现接口,也只能实现一个接口。
+匿名内部类与正规的继承相比有些受限,因为匿名内部类要么继承类,要么实现接口,但是不能两者兼备。而且如果是实现接口,也只能实现一个接口。
## 嵌套类
-如果不需要内部类对象与其外部类对象之间有联系,那么可以将内部类声明为 **static**,这通常称为嵌套类。想要理解 **static** 应用于内部类时的含义,就必须记住,普通的内部类对象隐式地保存了一个引用,指向创建它的外部类对象。然而,当内部类是 **static** 的时,就不是这样了。嵌套类意味着:
+如果不需要内部类对象与其外部类对象之间有联系,那么可以将内部类声明为 **static**,这通常称为*嵌套类*。想要理解 **static** 应用于内部类时的含义,就必须记住,普通的内部类对象隐式地保存了一个引用,指向创建它的外部类对象。然而,当内部类是 **static** 的时,就不是这样了。嵌套类意味着:
-1. 要创建嵌套类的对象,并不需要其外部类的对象。
+1. 创建嵌套类的对象时,不需要其外部类的对象。
2. 不能从嵌套类的对象中访问非静态的外部类对象。
嵌套类与普通的内部类还有一个区别。普通内部类的字段与方法,只能放在类的外部层次上,所以普通的内部类不能有 **static** 数据和 **static** 字段,也不能包含嵌套类。但是嵌套类可以包含所有这些东西:
@@ -910,7 +910,7 @@ Other operation
3
```
-这个例子进一步展示了外部类实现一个接口与内部类实现此接口之间的区别。就代码而言,**Callee1** 是更简单的解决方式。**Callee2** 继承自 **MyIncrement**,后者已经有了一个不同的 `increment()` 方法,并且与 **Incrementable** 接口期望的 `increment()` 方法完全不相关。所以如果 **Callee2** 继承了 **MyIncrement**,就不能为了 **Incrementable** 的用途而覆盖 `increment()` 方法,于是只能使用内部类独立地实现 **Incrementable**,还要注意,当创建了一个内部类时,并没有在外部类的接口中添加东西,也没有修改外部类的接口。
+这个例子进一步展示了外部类实现一个接口与内部类实现此接口之间的区别。就代码而言,**Callee1** 是更简单的解决方式。**Callee2** 继承自 **MyIncrement**,后者已经有了一个不同的 `increment()` 方法,并且与 **Incrementable** 接口期望的 `increment()` 方法完全不相关。所以如果 **Callee2** 继承了 **MyIncrement**,就不能为了 **Incrementable** 的用途而重写 `increment()` 方法,于是只能使用内部类独立地实现 **Incrementable**,还要注意,当创建了一个内部类时,并没有在外部类的接口中添加东西,也没有修改外部类的接口。
注意,在 **Callee2** 中除了 `getCallbackReference()` 以外,其他成员都是 **private** 的。要想建立与外部世界的任何连接,接口 **Incrementable** 都是必需的。在这里可以看到,**interface** 是如何允许接口与接口的实现完全独立的。
内部类 **Closure** 实现了 **Incrementable**,以提供一个返回 **Callee2** 的“钩子”(hook)-而且是一个安全的钩子。无论谁获得此 **Incrementable** 的引用,都只能调用 `increment()`,除此之外没有其他功能(不像指针那样,允许你做很多事情)。
@@ -923,13 +923,13 @@ Other operation
在将要介绍的控制框架(control framework)中,可以看到更多使用内部类的具体例子。
-应用程序框架(application framework)就是被设计用以解决某类特定问题的一个类或一组类。要运用某个应用程序框架,通常是继承一个或多个类,并覆盖某些方法。在覆盖后的方法中,编写代码定制应用程序框架提供的通用解决方案,以解决你的特定问题。这是设计模式中模板方法的一个例子,模板方法包含算法的基本结构,并且会调用一个或多个可覆盖的方法,以完成算法的动作。设计模式总是将变化的事物与保持不变的事物分离开,在这个模式中,模板方法是保持不变的事物,而可覆盖的方法就是变化的事物。
+应用程序框架(application framework)就是被设计用以解决某类特定问题的一个类或一组类。要运用某个应用程序框架,通常是继承一个或多个类,并重写某些方法。你在重写的方法中写的代码定制了该应用程序框架提供的通用解决方案,来解决你的具体问题。这是设计模式中*模板方法*的一个例子,模板方法包含算法的基本结构,而且会调用一个或多个可重写的方法来完成该算法的运算。设计模式总是将变化的事物与保持不变的事物分离开,在这个模式中,模板方法是保持不变的事物,而可重写的方法就是变化的事物。
控制框架是一类特殊的应用程序框架,它用来解决响应事件的需求。主要用来响应事件的系统被称作*事件驱动*系统。应用程序设计中常见的问题之一是图形用户接口(GUI),它几乎完全是事件驱动的系统。
-要理解内部类是如何允许简单的创建过程以及如何使用控制框架的,请考虑这样一个控制框架,它的工作就是在事件“就绪”的时候执行事件。虽然“就绪”可以指任何事,但在本例中是指基于时间触发的事件。接下来的问题就是,对于要控制什么,控制框架并不包含任何具体的信息。那些信息是在实现算法的 `action()` 部分时,通过继承来提供的。
+要理解内部类是如何允许简单的创建过程以及如何使用控制框架的,请考虑这样一个控制框架,它的工作就是在事件“就绪`ready()`”的时候执行事件。虽然“就绪”可以指任何事,但在本例中是指基于时间触发的事件。下面是一个控制框架,它不包含具体的控制信息。那些信息是通过继承(当算法的 `action()` 部分被实现时)来提供的。
-首先,接口描述了要控制的事件。因为其默认的行为是基于时间去执行控制,所以使用抽象类代替实际的接口。下面的例子包含了某些实现:
+这里是描述了所有控制事件的接口。之所以用抽象类代替了真正的接口,是因为默认行为都是根据时间来执行控制的。也因此包含了一些具体实现:
```java
// innerclasses/controller/Event.java
@@ -955,7 +955,7 @@ public abstract class Event {
当希望运行 **Event** 并随后调用 `start()` 时,那么构造器就会捕获(从对象创建的时刻开始的)时间,此时间是这样得来的:`start()` 获取当前时间,然后加上一个延迟时间,这样生成触发事件的时间。`start()` 是一个独立的方法,而没有包含在构造器内,因为这样就可以在事件运行以后重新启动计时器,也就是能够重复使用 **Event** 对象。例如,如果想要重复一个事件,只需简单地在 `action()` 中调用 `start()` 方法。
-`ready()` 告诉你何时可以运行 `action()` 方法了。当然,可以在派生类中覆盖 `ready()` 方法,使得 **Event** 能够基于时间以外的其他因素而触发。
+`ready()` 告诉你何时可以运行 `action()` 方法了。当然,可以在派生类中重写 `ready()` 方法,使得 **Event** 能够基于时间以外的其他因素而触发。
下面的文件包含了一个用来管理并触发事件的实际控制框架。**Event** 对象被保存在 **List**\<**Event**\> 类型(读作“Event 的列表”)的容器对象中,容器会在 [集合 ]() 中详细介绍。目前读者只需要知道 `add()` 方法用来将一个 **Event** 添加到 **List** 的尾端,`size()` 方法用来得到 **List** 中元素的个数,foreach 语法用来连续获取 **List** 中的 **Event**,`remove()` 方法用来从 **List** 中移除指定的 **Event**。
@@ -1150,7 +1150,7 @@ public class GreenhouseControls extends Controller {
一个由 **Event** 对象组成的数组被递交给 **Restart**,该数组要加到控制器上。由于 `Restart()` 也是一个 **Event** 对象,所以同样可以将 **Restart** 对象添加到 `Restart.action()` 中,以使系统能够有规律地重新启动自己。
-下面的类通过创建一个 **GreenhouseControls** 对象,并添加各种不同的 **Event** 对象来配置该系统,这是命令设计模式的一个例子—**eventList** 中的每个对象都被封装成对象的请求:
+下面的类通过创建一个 **GreenhouseControls** 对象,并添加各种不同的 **Event** 对象来配置该系统,这是 *命令* 设计模式的一个例子—**eventList** 中的每个对象都被封装成对象的请求:
```java
// innerclasses/GreenhouseController.java
@@ -1248,9 +1248,9 @@ enclosingClassReference.super();
-## 内部类可以被覆盖么?
+## 内部类可以被重写么?
-如果创建了一个内部类,然后继承其外部类并重新定义此内部类时,会发生什么呢?也就是说,内部类可以被覆盖吗?这看起来似乎是个很有用的思想,但是“覆盖”内部类就好像它是外部类的一个方法,其实并不起什么作用:
+如果创建了一个内部类,然后继承其外部类并重新定义此内部类时,会发生什么呢?也就是说,内部类可以被重写吗?这看起来似乎是个很有用的思想,但是“重写”内部类就好像它是外部类的一个方法,其实并不起什么作用:
```java
// innerclasses/BigEgg.java
@@ -1286,7 +1286,7 @@ New Egg()
Egg.Yolk()
```
-默认的无参构造器是编译器自动生成的,这里是调用基类的默认构造器。你可能认为既然创建了 **BigEgg** 的对象,那么所使用的应该是“覆盖后”的 **Yolk** 版本,但从输出中可以看到实际情况并不是这样的。
+默认的无参构造器是编译器自动生成的,这里是调用基类的默认构造器。你可能认为既然创建了 **BigEgg** 的对象,那么所使用的应该是“重写后”的 **Yolk** 版本,但从输出中可以看到实际情况并不是这样的。
这个例子说明,当继承了某个外部类的时候,内部类并没有发生什么特别神奇的变化。这两个内部类是完全独立的两个实体,各自在自己的命名空间内。当然,明确地继承某个内部类也是可以的:
@@ -1335,7 +1335,7 @@ BigEgg2.Yolk()
BigEgg2.Yolk.f()
```
-现在 **BigEgg2.Yolk** 通过 **extends Egg2.Yolk** 明确地继承了此内部类,并且覆盖了其中的方法。`insertYolk()` 方法允许 **BigEgg2** 将它自己的 **Yolk** 对象向上转型为 **Egg2** 中的引用 **y**。所以当 `g()` 调用 `y.f()` 时,覆盖后的新版的 `f()` 被执行。第二次调用 `Egg2.Yolk()`,结果是 **BigEgg2.Yolk** 的构造器调用了其基类的构造器。可以看到在调用 `g()` 的时候,新版的 `f()` 被调用了。
+现在 **BigEgg2.Yolk** 通过 **extends Egg2.Yolk** 明确地继承了此内部类,并且重写了其中的方法。`insertYolk()` 方法允许 **BigEgg2** 将它自己的 **Yolk** 对象向上转型为 **Egg2** 中的引用 **y**。所以当 `g()` 调用 `y.f()` 时,重写后的新版的 `f()` 被执行。第二次调用 `Egg2.Yolk()`,结果是 **BigEgg2.Yolk** 的构造器调用了其基类的构造器。可以看到在调用 `g()` 的时候,新版的 `f()` 被调用了。
@@ -1426,14 +1426,15 @@ Anonymous inner 9
```java
Counter.class
LocalInnerClass$1.class
-LocalInnerClass$LocalCounter.class
+LocalInnerClass$1LocalCounter.class
LocalInnerClass.class
```
如果内部类是匿名的,编译器会简单地产生一个数字作为其标识符。如果内部类是嵌套在别的内部类之中,只需直接将它们的名字加在其外部类标识符与 **"$"** 的后面。
-虽然这种命名格式简单而直接,但它还是很健壮的,足以应对绝大多数情况。因为这是 Java 的标准命名方式,所以产生的文件自动都是平台无关的。(注意,为了保证你的内部类能起作用,Java 编译器会尽可能地转换它们。)
+虽然这种命名格式简单而直接,但它还是很健壮的,足以应对绝大多数情况[^1]。因为这是 Java 的标准命名方式,所以产生的文件自动都是平台无关的。(注意,为了保证你的内部类能起作用,Java 编译器会尽可能地转换它们。)
+- **[1]** 另一方面,**$** 对Unix shell来说是一个元字符,所以当你列出.class文件时,有时会遇到麻烦。这对基于Unix的Sun公司来说有点奇怪。我的猜测是,他们没有考虑这个问题,而是认为你会很自然地关注源代码文件。
## 本章小结
From a6fb15b05d276e64cca5934282fdac94e457ed18 Mon Sep 17 00:00:00 2001
From: andyphone <792998301@qq.com>
Date: Thu, 3 Dec 2020 10:58:22 +0800
Subject: [PATCH 43/68] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AF=AD=E5=8F=A5?=
=?UTF-8?q?=E6=8B=97=E5=8F=A3=E9=97=AE=E9=A2=98=20(#626)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* 1
* 2
* 没有第三种形式吧?
* 修改语句拗口问题
* 修改语句拗口问题 2
* 修改语句拗口问题 3
* 修改语句拗口问题 4
* 修改语句拗口问题 5
* 修改语句拗口问题 6
* 修改语句拗口问题 7
* 修改语句拗口问题 8
* 修改语句拗口问题 9
* 拗口问题
* 修改语句拗口问题 10
* 修改语句拗口问题 11
* 修改语句拗口问题 12
* 修改语句拗口问题 13
* 修改语句拗口问题 14
* 修改语句拗口问题 14
* 修改语句拗口问题 15
---
docs/book/08-Reuse.md | 22 ++++++++-------
docs/book/11-Inner-Classes.md | 2 +-
docs/book/12-Collections.md | 52 +++++++++++++++++------------------
3 files changed, 39 insertions(+), 37 deletions(-)
diff --git a/docs/book/08-Reuse.md b/docs/book/08-Reuse.md
index e10f8751..cf27c665 100644
--- a/docs/book/08-Reuse.md
+++ b/docs/book/08-Reuse.md
@@ -690,9 +690,9 @@ doh(Milhouse)
````
-**Homer** 的所有重载方法在 **Bart** 中都是可用的,尽管 **Bart** 引入了一种新的重载方法。正如你将在下一章中看到的那样,比起重载,更常见的是覆盖同名方法,使用与基类中完全相同的方法签名[^1]和返回类型。否则会让人感到困惑。
+**Homer** 的所有重载方法在 **Bart** 中都是可用的,尽管 **Bart** 引入了一种新的重载方法。正如你将在下一章中看到的那样,比起重载,更常见的是覆盖同名方法,使用与基类中完全相同的方法签名[^2]和返回类型。否则会让人感到困惑。
-你已经看到了Java 5 **@Override**注解,它不是关键字,但是可以像使用关键字一样使用它。当你打算重写一个方法[^2]时,你可以选择添加这个注解,如果你不小心用了重载而不是重写,编译器会产生一个错误消息:
+你已经看到了Java 5 **@Override**注解,它不是关键字,但是可以像使用关键字一样使用它。当你打算重写一个方法[^3]时,你可以选择添加这个注解,如果你不小心用了重载而不是重写,编译器会产生一个错误消息:
```java
@@ -712,12 +712,7 @@ class Lisa extends Homer {
**{WillNotCompile}** 标记将该文件排除在本书的 **Gradle** 构建之外,但是如果你手工编译它,你将看到:method does not override a method from its superclass.方法不会重写超类中的方法, **@Override** 注解能防止你意外地重载。
-- **[1]** 方法签名——方法名和参数类型的合称
-
-- **[2]** 重写——覆盖同名方法,使用与基类中完全相同的方法签名和返回类型[^3]
-
-- **[3]** 在java 1.4版本以前,重写方法的返回值类型被要求必须与被重写方法一致,但是在java 5.0中放宽了这一个限制,添加了对协变返回类型的支持,在重写的时候,重写方法的返回值类型可以是被重写方法返回值类型的子类。
-
+
## 组合与继承的选择
@@ -1182,8 +1177,6 @@ Java 标准类库就是一个很好的例子。尤其是 Java 1.0/1.1 的 **Vect
Java 1.0/1.1 标准类库中另一个重要的类是 **Hashtable**(后来被 **HashMap** 取代),它不含任何 **final** 方法。本书中其他地方也提到,很明显不同的类是由不同的人设计的。**Hashtable** 就比 **Vector** 中的方法名简洁得多,这又是一条证据。对于类库的使用者来说,这是一个本不应该如此草率的事情。这种不规则的情况造成用户需要做更多的工作——这是对粗糙的设计和代码的又一讽刺。
-- **[1]** Java 1.4 开始已将 **Vector** 类大多数方法的 **final** 去掉
-
## 类初始化和加载
@@ -1267,6 +1260,15 @@ j = 39
当开始设计一个系统时,记住程序开发是一个增量过程,正如人类学习。它依赖实验,你可以尽可能多做分析,然而在项目开始时仍然无法知道所有的答案。如果把项目视作一个有机的,进化着的生命去培养,而不是视为像摩天大楼一样快速见效,就能获得更多的成功和更迅速的反馈。继承和组合正是可以让你执行如此实验的面向对象编程中最基本的两个工具。
+[^1]: Java 1.4 开始已将 **Vector** 类大多数方法的 **final** 去掉
+
+[^2]: 方法签名——方法名和参数类型的合称
+
+[^3]: 重写——覆盖同名方法,使用与基类中完全相同的方法签名和返回类型[^4]
+
+[^4]: 在java 1.4版本以前,重写方法的返回值类型被要求必须与被重写方法一致,但是在java 5.0中放宽了这一个限制,添加了对协变返回类型的支持,在重写的时候,重写方法的返回值类型可以是被重写方法返回值类型的子类。
+
+
diff --git a/docs/book/11-Inner-Classes.md b/docs/book/11-Inner-Classes.md
index 83376eb8..caf557e8 100755
--- a/docs/book/11-Inner-Classes.md
+++ b/docs/book/11-Inner-Classes.md
@@ -1434,7 +1434,7 @@ LocalInnerClass.class
虽然这种命名格式简单而直接,但它还是很健壮的,足以应对绝大多数情况[^1]。因为这是 Java 的标准命名方式,所以产生的文件自动都是平台无关的。(注意,为了保证你的内部类能起作用,Java 编译器会尽可能地转换它们。)
-- **[1]** 另一方面,**$** 对Unix shell来说是一个元字符,所以当你列出.class文件时,有时会遇到麻烦。这对基于Unix的Sun公司来说有点奇怪。我的猜测是,他们没有考虑这个问题,而是认为你会很自然地关注源代码文件。
+[^1]: 另一方面,**$** 对Unix shell来说是一个元字符,所以当你列出.class文件时,有时会遇到麻烦。这对基于Unix的Sun公司来说有点奇怪。我的猜测是,他们没有考虑这个问题,而是认为你会很自然地关注源代码文件。
## 本章小结
diff --git a/docs/book/12-Collections.md b/docs/book/12-Collections.md
index 269fc785..131d1771 100644
--- a/docs/book/12-Collections.md
+++ b/docs/book/12-Collections.md
@@ -17,12 +17,12 @@ MyType aReference;
集合还有一些其它特性。例如, **Set** 对于每个值都只保存一个对象, **Map** 是一个关联数组,允许将某些对象与其他对象关联起来。Java集合类都可以自动地调整自己的大小。因此,与数组不同,在编程时,可以将任意数量的对象放置在集合中,而不用关心集合应该有多大。
-尽管在 Java 中没有直接的关键字支持,[^1]但集合类仍然是可以显著增强编程能力的基本工具。在本章中,将介绍 Java 集合类库的基本知识,并重点介绍一些典型用法。这里将专注于在日常编程中使用的集合。稍后,在[附录:集合主题]()中,还将学习到其余的那些集合和相关功能,以及如何使用它们的更多详细信息。
+尽管在 Java 中没有直接的关键字支持[^1],但集合类仍然是可以显著增强编程能力的基本工具。在本章中,将介绍 Java 集合类库的基本知识,并重点介绍一些典型用法。这里将专注于在日常编程中使用的集合。稍后,在[附录:集合主题]()中,还将学习到其余的那些集合和相关功能,以及如何使用它们的更多详细信息。
## 泛型和类型安全的集合
-使用 Java 5 之前的集合的一个主要问题是编译器允许你向集合中插入不正确的类型。例如,考虑一个 **Apple** 对象的集合,这里使用最基本最可靠的 **ArrayList** 。现在,可以把 **ArrayList** 看作“可以自动扩充自身尺寸的数组”来看待。使用 **ArrayList** 相当简单:创建一个实例,用 `add()` 插入对象;然后用 `get()` 来访问这些对象,此时需要使用索引,就像数组那样,但是不需要方括号。[^2] **ArrayList** 还有一个 `size()` 方法,来说明集合中包含了多少个元素,所以不会不小心因数组越界而引发错误(通过抛出*运行时异常*,[异常]()章节介绍了异常)。
+使用 Java 5 之前的集合的一个主要问题是编译器允许你向集合中插入不正确的类型。例如,考虑一个 **Apple** 对象的集合,这里使用最基本最可靠的 **ArrayList** 。现在,可以把 **ArrayList** 看作“可以自动扩充自身尺寸的数组”来看待。使用 **ArrayList** 相当简单:创建一个实例,用 `add()` 插入对象;然后用 `get()` 来访问这些对象,此时需要使用索引,就像数组那样,但是不需要方括号[^2]。 **ArrayList** 还有一个 `size()` 方法,来说明集合中包含了多少个元素,所以不会不小心因数组越界而引发错误(通过抛出*运行时异常*,[异常]()章节介绍了异常)。
在本例中, **Apple** 和 **Orange** 都被放到了集合中,然后将它们取出。正常情况下,Java编译器会给出警告,因为这个示例没有使用泛型。在这里,使用特定的注解来抑制警告信息。注解以“@”符号开头,可以带参数。这里的 `@SuppressWarning` 注解及其参数表示只抑制“unchecked”类型的警告([注解]()章节将介绍更多有关注解的信息):
@@ -70,7 +70,7 @@ ndOrangesWithoutGenerics.java:23)
在[泛型]()章节中,你将了解到使用 Java 泛型来创建类可能很复杂。但是,使用预先定义的泛型类却相当简单。例如,要定义一个用于保存 **Apple** 对象的 **ArrayList** ,只需要使用 **ArrayList\** 来代替 **ArrayList** 。尖括号括起来的是*类型参数*(可能会有多个),它指定了这个集合实例可以保存的类型。
-通过使用泛型,就可以在编译期防止将错误类型的对象放置到集合中。[^3]下面还是这个示例,但是使用了泛型:
+通过使用泛型,就可以在编译期防止将错误类型的对象放置到集合中[^3]。下面还是这个示例,但是使用了泛型:
```java
// collections/ApplesAndOrangesWithGenerics.java
import java.util.*;
@@ -310,7 +310,7 @@ public class PrintingCollections {
*/
```
-这显示了Java集合库中的两个主要类型。它们的区别在于集合中的每个“槽”(slot)保存的元素个数。 **Collection** 类型在每个槽中只能保存一个元素。此类集合包括: **List** ,它以特定的顺序保存一组元素; **Set** ,其中元素不允许重复; **Queue** ,只能在集合一端插入对象,并从另一端移除对象(就本例而言,这只是查看序列的另一种方式,因此并没有显示它)。 **Map** 在每个槽中存放了两个元素,即*键*和与之关联的*值*。
+这显示了Java集合库中的两个主要类型。它们的区别在于集合中的每个“槽”(slot)保存的元素个数。 **Collection** 类型在每个槽中只能保存一个元素。此类集合包括: **List** ,它以特定的顺序保存一组元素; **Set** ,其中元素不允许重复; **Queue** ,只能在集合一端插入对象,并从另一端移除对象(就本例而言,这只是查看序列的另一种方式,因此并没有显示它)。 **Map** 在每个槽中存放了两个元素,即*键* (key)和与之关联的*值* (value)。
默认的打印行为,使用集合提供的 `toString()` 方法即可生成可读性很好的结果。 **Collection** 打印出的内容用方括号括住,每个元素由逗号分隔。 **Map** 则由大括号括住,每个键和值用等号连接(键在左侧,值在右侧)。
@@ -318,7 +318,7 @@ public class PrintingCollections {
**ArrayList** 和 **LinkedList** 都是 **List** 的类型,从输出中可以看出,它们都按插入顺序保存元素。两者之间的区别不仅在于执行某些类型的操作时的性能,而且 **LinkedList** 包含的操作多于 **ArrayList** 。本章后面将对这些内容进行更全面的探讨。
-**HashSet** , **TreeSet** 和 **LinkedHashSet** 是 **Set** 的类型。从输出中可以看到, **Set** 仅保存每个相同项中的一个,并且不同的 **Set** 实现存储元素的方式也不同。 **HashSet** 使用相当复杂的方法存储元素,这在[附录:集合主题]()中进行了探讨。现在只需要知道,这种技术是检索元素的最快方法,因此,存储顺序看上去没有什么意义(通常只关心某事物是否是 **Set** 的成员,而存储顺序并不重要)。如果存储顺序很重要,则可以使用 **TreeSet** ,它将按比较结果的升序保存对象)或 **LinkedHashSet** ,它按照被添加的先后顺序保存对象。
+**HashSet** , **TreeSet** 和 **LinkedHashSet** 是 **Set** 的类型。从输出中可以看到, **Set** 仅保存每个相同项中的一个,并且不同的 **Set** 实现存储元素的方式也不同。 **HashSet** 使用相当复杂的方法存储元素,这在[附录:集合主题]()中进行了探讨。现在只需要知道,这种技术是检索元素的最快方法,因此,存储顺序看上去没有什么意义(通常只关心某事物是否是 **Set** 的成员,而存储顺序并不重要)。如果存储顺序很重要,则可以使用 **TreeSet** ,它把对象按照比较规则来排序;还有 **LinkedHashSet** ,它把对象按照被添加的先后顺序来排序。
**Map** (也称为*关联数组*)使用*键*来查找对象,就像一个简单的数据库。所关联的对象称为*值*。 假设有一个 **Map** 将美国州名与它们的首府联系在一起,如果想要俄亥俄州(Ohio)的首府,可以用“Ohio”作为键来查找,几乎就像使用数组下标一样。正是由于这种行为,对于每个键, **Map** 只存储一次。
@@ -328,7 +328,7 @@ public class PrintingCollections {
本例使用了 **Map** 的三种基本风格: **HashMap** , **TreeMap** 和 **LinkedHashMap** 。
-键和值保存在 **HashMap** 中的顺序不是插入顺序,因为 **HashMap** 实现使用了非常快速的算法来控制顺序。 **TreeMap** 通过比较结果的升序来保存键, **LinkedHashMap** 在保持 **HashMap** 查找速度的同时按键的插入顺序保存键。
+键和值保存在 **HashMap** 中的顺序不是插入顺序,因为 **HashMap** 实现使用了非常快速的算法来控制顺序。 **TreeMap** 把所有的键按照比较规则来排序, **LinkedHashMap** 在保持 **HashMap** 查找速度的同时按照键的插入顺序来排序。
@@ -729,7 +729,7 @@ pets.removeLast(): Hamster
堆栈是“后进先出”(LIFO)集合。它有时被称为*叠加栈*(pushdown stack),因为最后“压入”(push)栈的元素,第一个被“弹出”(pop)栈。经常用来类比栈的事物是带有弹簧支架的自助餐厅托盘。最后装入的托盘总是最先拿出来使用的。
-Java 1.0 中附带了一个 **Stack** 类,结果设计得很糟糕(为了向后兼容,我们永远坚持 Java 中的旧设计错误)。Java 6 添加了 **ArrayDeque** ,其中包含直接实现堆栈功能的方法:
+Java 1.0 中附带了一个 **Stack** 类,结果设计得很糟糕(为了向后兼容,我们被迫一直忍受 Java 中的旧设计错误)。Java 6 添加了 **ArrayDeque** ,其中包含直接实现堆栈功能的方法:
```java
// collections/StackTest.java
@@ -861,7 +861,7 @@ public class SetOfInteger {
在 0 到 29 之间的 10000 个随机整数被添加到 **Set** 中,因此可以想象每个值都重复了很多次。但是从结果中可以看到,每一个数只有一个实例出现在结果中。
-早期 Java 版本中的 **HashSet** 产生的输出没有可辨别的顺序。这是因为出于对速度的追求, **HashSet** 使用了散列,请参阅[附录:集合主题]()一章。由 **HashSet** 维护的顺序与 **TreeSet** 或 **LinkedHashSet** 不同,因为它们的实现具有不同的元素存储方式。 **TreeSet** 将元素存储在红-黑树数据结构中,而 **HashSet** 使用散列函数。 **LinkedHashSet** 因为查询速度的原因也使用了散列,但是看起来使用了链表来维护元素的插入顺序。看起来散列算法好像已经改变了,现在 **Integer** 按顺序排序。但是,您不应该依赖此行为:
+早期 Java 版本中的 **HashSet** 产生的输出没有明显的顺序。这是因为出于对速度的追求, **HashSet** 使用了散列,请参阅[附录:集合主题]()一章。由 **HashSet** 维护的顺序与 **TreeSet** 或 **LinkedHashSet** 不同,因为它们的实现具有不同的元素存储方式。 **TreeSet** 将元素存储在红-黑树数据结构中,而 **HashSet** 使用散列函数。 **LinkedHashSet** 也使用散列来提高查询速度,但是似乎使用了链表来维护元素的插入顺序。显然,散列算法有改动,以至于现在(上述示例中的HashSet ) **Integer** 是有序的。但是,您不应该依赖此行为(下面例子就没有排序):
```java
// collections/SetOfString.java
@@ -990,7 +990,7 @@ void]
*/
```
-我们逐步浏览文件中的每一行,并使用 `String.split()` 将其分解为单词,这里使用正则表达式 **\\\ W +** ,这意味着它会依据一个或多个(即 **+** )非单词字母来拆分字符串(正则表达式将在[字符串]()章节介绍)。每个结果单词都会添加到 **Set words** 中。因为它是 **TreeSet** ,所以对结果进行排序。这里,排序是按*字典顺序*(lexicographically)完成的,因此大写和小写字母位于不同的组中。如果想按*字母顺序*(alphabetically)对其进行排序,可以向 **TreeSet** 构造器传入 **String.CASE_INSENSITIVE_ORDER** 比较器(比较器是一个建立排序顺序的对象):
+我们逐步浏览文件中的每一行,并使用 `String.split()` 将其分解为单词,这里使用正则表达式 **\\\ W +** ,这意味着它会依据一个或多个(即 **+** )非单词字母来拆分字符串(正则表达式将在[字符串]()章节介绍)。每个结果单词都会添加到 **Set words** 中。因为它是 **TreeSet** ,所以对结果进行排序。这里,排序是按*字典顺序*(lexicographically)完成的,因此大写字母和小写字母是分开的。如果想按*字母顺序*(alphabetically)对其进行排序,可以向 **TreeSet** 构造器传入 **String.CASE_INSENSITIVE_ORDER** 比较器(比较器是一个建立排序顺序的对象):
```java
// collections/UniqueWordsAlphabetic.java
@@ -1088,7 +1088,7 @@ true
*/
```
-**Map** 与数组和其他的 **Collection** 一样,可以轻松地扩展到多个维度,只需要创建一个值为 **Map** 的 **Map**(这些 **Map** 的值可以是其他集合,甚至是其他 **Map**)。因此,能够很容易地将集合组合起来以快速生成强大的数据结构。例如,假设你正在追踪有多个宠物的人,只需要一个 **Map\>** 即可:
+**Map** 与数组和其他的 **Collection** 一样,可以轻松地扩展到多个维度:只需要创建一个 **Map** ,其值也是 **Map** (这些 **Map** 的值可以是其他集合,甚至是其他的 **Map** )。因此,能够很容易地将集合组合起来以快速生成强大的数据结构。例如,假设你正在追踪有多个宠物的人,只需要一个 **Map\>** 即可:
```java
@@ -1164,7 +1164,7 @@ Person Luke has:
队列是一个典型的“先进先出”(FIFO)集合。 即从集合的一端放入事物,再从另一端去获取它们,事物放入集合的顺序和被取出的顺序是相同的。队列通常被当做一种可靠的将对象从程序的某个区域传输到另一个区域的途径。队列在[并发编程]()中尤为重要,因为它们可以安全地将对象从一个任务传输到另一个任务。
-**LinkedList** 实现了 **Queue** 接口,并且提供了一些方法以支持队列行为,因此 **LinkedList** 可以用作 **Queue** 的一种实现。 通过将 **LinkedList** 向上转换为 **Queue** ,下面的示例使用了在 **Queue** 接口中与 **Queue** 相关(Queue-specific)的方法:
+**LinkedList** 实现了 **Queue** 接口,并且提供了一些方法以支持队列行为,因此 **LinkedList** 可以用作 **Queue** 的一种实现。 通过将 **LinkedList** 向上转换为 **Queue** ,下面的示例使用了在 **Queue** 接口中的 **Queue** 特有(Queue-specific)方法:
```java
// collections/QueueDemo.java
@@ -1195,18 +1195,18 @@ B r o n t o s a u r u s
*/
```
-`offer()` 是与 **Queue** 相关的方法之一,它在允许的情况下,在队列的尾部插入一个元素,或者返回 **false** 。 `peek()` 和 `element()` 都返回队头元素而不删除它,但是如果队列为空,则 `element()` 抛出 **NoSuchElementException** ,而 `peek()` 返回 **null** 。 `poll()` 和 `remove()`* 都删除并返回队头元素,但如果队列为空,`poll()` 返回 **null** ,而 `remove()` 抛出 **NoSuchElementException** 。
+`offer()` 是 **Queue** 的特有方法之一,它在允许的情况下,在队列的尾部插入一个元素,或者返回 **false** 。 `peek()` 和 `element()` 都返回队头元素而不删除它,但如果队列为空,则 `peek()` 返回 **null** , 而 `element()` 抛出 **NoSuchElementException** 。 `poll()` 和 `remove()` 都删除并返回队头元素,但如果队列为空,则 `poll()` 返回 **null** ,而 `remove()` 抛出 **NoSuchElementException** 。
自动包装机制会自动将 `nextInt()` 的 **int** 结果转换为 **queue** 所需的 **Integer** 对象,并将 **char c** 转换为 **qc** 所需的 **Character** 对象。 **Queue** 接口窄化了对 **LinkedList** 方法的访问权限,因此只有适当的方法才能使用,因此能够访问到的 **LinkedList** 的方法会变少(这里实际上可以将 **Queue** 强制转换回 **LinkedList** ,但至少我们不鼓励这样做)。
-与 **Queue** 相关的方法提供了完整而独立的功能。 也就是说,对于 **Queue** 所继承的 **Collection** ,在不需要使用它的任何方法的情况下,就可以拥有一个可用的 **Queue** 。
+**Queue** 的特有方法提供了独立而完整的功能。 换句话说, **Queue** 无需调用继承自 **Collection** 的方法,(只依靠 **Queue** 的特有方法)就有队列的功能。
### 优先级队列PriorityQueue
-先进先出(FIFO)描述了最典型的*队列规则*(queuing discipline)。队列规则是指在给定队列中的一组元素的情况下,确定下一个弹出队列的元素的规则。先进先出声明的是下一个弹出的元素应该是等待时间最长的元素。
+先进先出(FIFO)描述了最典型的*队列规则*(queuing discipline)。队列规则是指在给定队列中的一组元素的情况下,确定下一个弹出队列的元素的规则。先进先出:下一个弹出的元素应该是等待时间最长的那一个。
-优先级队列声明下一个弹出的元素是最需要的元素(具有最高的优先级)。例如,在机场,当飞机临近起飞时,这架飞机的乘客可以在办理登机手续时排到队头。如果构建了一个消息传递系统,某些消息比其他消息更重要,应该尽快处理,而不管它们何时到达。在Java 5 中添加了 **PriorityQueue** ,以便自动实现这种行为。
+*优先级队列* :下一个弹出的元素是最需要的元素(具有最高的优先级)。例如,在机场,飞机即将起飞的、尚未登机的乘客可能会被拉出队伍(作最优先的处理)。如果构建了一个消息传递系统,某些消息比其他消息更重要,应该尽快处理,而不管它们到达时间先后。在Java 5 中添加了 **PriorityQueue** ,以便自动实现这种行为。
当在 **PriorityQueue** 上调用 `offer()` 方法来插入一个对象时,该对象会在队列中被排序。[^5]默认的排序使用队列中对象的*自然顺序*(natural order),但是可以通过提供自己的 **Comparator** 来修改这个顺序。 **PriorityQueue** 确保在调用 `peek()` , `poll()` 或 `remove()` 方法时,获得的元素将是队列中优先级最高的元素。
@@ -1274,9 +1274,9 @@ C B A A
## 集合与迭代器
-**Collection** 是所有序列集合共有的根接口。它可能会被认为是一种“附属接口”(incidental interface),即因为要表示其他若干个接口的共性而出现的接口。此外,**java.util.AbstractCollection** 类提供了 **Collection** 的默认实现,使得你可以创建 **AbstractCollection** 的子类型,而其中没有不必要的代码重复。
+**Collection** 是所有序列集合共有的根接口。它可能会被认为是一种“附属接口”(incidental interface),即因为要表示其他若干个接口的共性而出现的接口。此外,**java.util.AbstractCollection** 类提供了 **Collection** 的默认实现,你可以创建 **AbstractCollection** 的子类型来避免不必要的代码重复。
-使用接口描述的一个理由是它可以使我们创建更通用的代码。通过针对接口而非具体实现来编写代码,我们的代码可以应用于更多类型的对象。[^6]因此,如果所编写的方法接受一个 **Collection** ,那么该方法可以应用于任何实现了 **Collection** 的类——这也就使得一个新类可以选择去实现 **Collection** 接口,以便该方法可以使用它。标准 C++ 类库中的集合并没有共同的基类——集合之间的所有共性都是通过迭代器实现的。在 Java 中,遵循 C++ 的方式看起来似乎很明智,即用迭代器而不是 **Collection** 来表示集合之间的共性。但是,这两种方法绑定在了一起,因为实现 **Collection** 就意味着需要提供 `iterator()` 方法:
+使用接口的一个理由是它可以使我们创建更通用的代码。通过针对接口而非具体实现来编写代码,我们的代码可以应用于更多类型的对象。[^6]因此,如果所编写的方法接受一个 **Collection** ,那么该方法可以应用于任何实现了 **Collection** 的类——这也就使得一个新类可以选择去实现 **Collection** 接口,以便该方法可以使用它。标准 C++ 类库中的集合并没有共同的基类——集合之间的所有共性都是通过迭代器实现的。在 Java 中,遵循 C++ 的方式看起来似乎很明智,即用迭代器而不是 **Collection** 来表示集合之间的共性。但是,这两种方法绑定在了一起,因为实现 **Collection** 就意味着需要提供 `iterator()` 方法:
```java
// collections/InterfaceVsIterator.java
@@ -1337,7 +1337,7 @@ Britney=Pug, Sam=Cymric, Spot=Pug, Fluffy=Manx}
在本例中,这两种方式都可以奏效。事实上, **Collection** 要更方便一点,因为它是 **Iterable** 类型,因此在 `display(Collection)` 的实现中可以使用 *for-in* 构造,这使得代码更加清晰。
-当需要实现一个不是 **Collection** 的外部类时,由于让它去实现 **Collection** 接口可能非常困难或麻烦,因此使用 **Iterator** 就会变得非常吸引人。例如,如果我们通过继承一个持有 **Pet** 对象的类来创建一个 **Collection** 的实现,那么我们必须实现 **Collection** 所有的方法,即使我们不在 `display()` 方法中使用它们,也必须这样做。虽然这可以通过继承 **AbstractCollection** 而很容易地实现,但是无论如何还是要被强制去实现 `iterator()` 和 `size()` 方法,这些方法 **AbstractCollection** 没有实现,但是 **AbstractCollection** 中的其它方法会用到:
+当需要实现一个不是 **Collection** 的外部类时,由于让它去实现 **Collection** 接口可能非常困难或麻烦,因此使用 **Iterator** 就会变得非常吸引人。例如,如果我们通过继承一个持有 **Pet** 对象的类来创建一个 **Collection** 的实现,那么我们必须实现 **Collection** 所有的方法,纵使我们不会在 `display()` 方法中使用它们,也要这样做。尽管通过继承 **AbstractCollection** 会容易些,但是 **AbstractCollection** 还有 `iterator()` 和 `size()`没有实现(抽象方法),而 **AbstractCollection** 中的其它方法会用到它们,因此必须以自己的方式实现这两个方法:
```java
// collections/CollectionSequence.java
@@ -1383,7 +1383,7 @@ extends AbstractCollection {
- **[1]** 你可能会认为,因为 `iterator()` 返回 **Iterator\** ,匿名内部类定义可以使用菱形语法,Java可以推断出类型。但这不起作用,类型推断仍然非常有限。
-这个例子表明,如果实现了 **Collection** ,就必须实现 `iterator()` ,并且只拿实现 `iterator()` 与继承 **AbstractCollection** 相比,花费的代价只有略微减少。但是,如果类已经继承了其他的类,那么就不能再继承 **AbstractCollection** 了。在这种情况下,要实现 **Collection** ,就必须实现该接口中的所有方法。此时,继承并提供创建迭代器的能力要容易得多:
+这个例子表明,如果实现了 **Collection** ,就必须也实现 `iterator()` ,而单独只实现 `iterator()` 和继承 **AbstractCollection** 相比,并没有容易多少。但是,如果类已经继承了其他的类,那么就没法再继承 **AbstractCollection** 了。在这种情况下,要实现 **Collection** ,就必须实现该接口中的所有方法。此时,继承并提供创建迭代器的能力(单独只实现 `iterator()`)要容易得多:
```java
// collections/NonCollectionSequence.java
@@ -1422,12 +1422,12 @@ public class NonCollectionSequence extends PetSequence {
*/
```
-生成 **Iterator** 是将序列与消费该序列的方法连接在一起耦合度最小的方式,并且与实现 **Collection** 相比,它在序列类上所施加的约束也少得多。
+生成 **Iterator** 是将序列与消费该序列的方法连接在一起的耦合度最小的方式,并且与实现 **Collection** 相比,它在序列类上所施加的约束也少得多。
## for-in和迭代器
-到目前为止,*for-in* 语法主要用于数组,但它也适用于任何 **Collection** 对象。实际上在使用 **ArrayList** 时,已经看到了一些使用它的示例,下面是一个更通用的证明:
+到目前为止,*for-in* 语法主要用于数组,但它也适用于任何 **Collection** 对象。实际上在使用 **ArrayList** 时,已经看到了一些使用它的示例,下面是它的通用性的证明:
```java
// collections/ForInCollections.java
@@ -1508,7 +1508,7 @@ public class EnvironmentVariables {
`System.getenv()` [^7]返回一个 **Map** , `entrySet()` 产生一个由 **Map.Entry** 的元素构成的 **Set** ,并且这个 **Set** 是一个 **Iterable** ,因此它可以用于 *for-in* 循环。
-*for-in* 语句适用于数组或其它任何 **Iterable** ,但这并不意味着数组肯定也是个 **Iterable** ,也不会发生任何自动装箱:
+*for-in* 语句适用于数组或者其它任何 **Iterable** ,但这并不代表数组一定是 **Iterable** ,也不会发生任何自动装箱:
```java
// collections/ArrayIsNotIterable.java
@@ -1684,7 +1684,7 @@ array: [9, 1, 6, 3, 7, 2, 5, 10, 4, 8]
*/
```
-在第一种情况下, `Arrays.asList()` 的输出被传递给了 **ArrayList** 的构造器,这将创建一个引用 **ia** 的元素的 **ArrayList** ,因此打乱这些引用不会修改该数组。但是,如果直接使用 `Arrays.asList(ia)` 的结果,这种打乱就会修改 **ia** 的顺序。重要的是要注意 `Arrays.asList()` 生成一个 **List** 对象,该对象使用底层数组作为其物理实现。如果执行的操作会修改这个 **List** ,并且不希望修改原始数组,那么就应该在另一个集合中创建一个副本。
+在第一种情况下, `Arrays.asList()` 的输出被传递给了 **ArrayList** 的构造器,这将创建一个引用 **ia** 的元素的 **ArrayList** ,因此打乱这些引用不会修改该数组。但是,如果直接使用 `Arrays.asList(ia)` 的结果,这种打乱就会修改 **ia** 的顺序。重要的是要注意 `Arrays.asList()` 生成一个 **List** 对象,该对象使用底层数组作为其物理实现。如果对 **List** 对象做了任何修改,又不想让原始数组被修改,那么就应该在另一个集合中创建一个副本。
## 本章小结
@@ -1804,11 +1804,11 @@ Serializable]
[^3]: 在[泛型]()章节的末尾,有个关于这个问题是否很严重的讨论。但是,[泛型]()章节还将展示Java泛型远不止是类型安全的集合这么简单。
-[^4]: `remove()` 是一个所谓的“可选”方法(还有一些其它的这种方法),这意味着并非所有的 **Iterator** 实现都必须实现该方法。这个问题将在[附录:集合主题]()中介绍。但是,标准 Java 库集合实现了 `remove()` ,因此在[附录:集合主题]()章节之前,都不必担心这个问题。
+[^4]: `remove()` 是一个所谓的“可选”方法(还有其它这样的方法),这意味着并非所有的 **Iterator** 实现都必须实现该方法。这个问题将在[附录:集合主题]()中介绍。但是,标准 Java 库集合实现了 `remove()` ,因此在[附录:集合主题]()章节之前,都不必担心这个问题。
-[^5]: 这实际上依赖于具体实现。优先级队列算法通常会按插入顺序排序(维护一个*堆*),但它们也可以在删除时选择最重要的元素。 如果对象的优先级在它在队列中等待时可以修改,那么算法的选择就显得很重要了。
+[^5]: 这实际上依赖于具体实现。优先级队列算法通常会按插入顺序排序(维护一个*堆*),但它们也可以在删除时选择最重要的元素。 如果一个对象在队列中等待时,它的优先级会发生变化,那么算法的选择就很重要。
-[^6]: 有些人提倡这样一种自动创建机制,即对一个类中所有可能的方法组合都自动创建一个接口,有时候对于单个的类都是如此。 我相信接口的意义不应该仅限于方法组合的机械地复制,因此我在创建接口之前,总是要先看到增加接口带来的价值。
+[^6]: 有些人鼓吹不加思索地创建接口对应一个类甚至每个类中的所有可能的方法组合。 但我相信接口的意义不应该仅限于机械地重复方法组合,因此我倾向于看到增加接口的价值才创建它。
[^7]: 这在 Java 5 之前是不可用的,因为该方法被认为与操作系统的耦合度过紧,因此违反“一次编写,处处运行”的原则。现在却提供它,这一事实表明, Java 的设计者们更加务实了。
From e2c50c2c750c175478074debf19a894a28919587 Mon Sep 17 00:00:00 2001
From: andyphone <792998301@qq.com>
Date: Mon, 7 Dec 2020 11:07:49 +0800
Subject: [PATCH 44/68] =?UTF-8?q?=E5=8D=81=E4=B8=89=E7=AB=A0=E4=BF=AE?=
=?UTF-8?q?=E6=94=B9=E8=AF=AD=E5=8F=A5=E6=8B=97=E5=8F=A3=E9=97=AE=E9=A2=98?=
=?UTF-8?q?=20=20(#630)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* 1
* 2
* 没有第三种形式吧?
* 修改语句拗口问题
* 修改语句拗口问题 2
* 修改语句拗口问题 3
* 修改语句拗口问题 4
* 修改语句拗口问题 5
* 修改语句拗口问题 6
* 修改语句拗口问题 7
* 修改语句拗口问题 8
* 修改语句拗口问题 9
* 拗口问题
* 修改语句拗口问题 10
* 修改语句拗口问题 11
* 修改语句拗口问题 12
* 修改语句拗口问题 13
* 修改语句拗口问题 14
* 修改语句拗口问题 14
* 修改语句拗口问题 15
* 修改语句拗口问题 16
* 修改语句拗口问题 17
* 十三章修改语句拗口问题
---
docs/book/12-Collections.md | 4 +-
docs/book/13-Functional-Programming.md | 74 +++++++++++++-------------
2 files changed, 39 insertions(+), 39 deletions(-)
diff --git a/docs/book/12-Collections.md b/docs/book/12-Collections.md
index 131d1771..e34688fa 100644
--- a/docs/book/12-Collections.md
+++ b/docs/book/12-Collections.md
@@ -1538,10 +1538,10 @@ public class ArrayIsNotIterable {
### 适配器方法惯用法
-如果现在有一个 **Iterable** 类,你想要添加一种或多种在 *for-in* 语句中使用这个类的方法,应该怎么做呢?例如,你希望可以选择正向还是反向遍历一个单词列表。如果直接继承这个类,并覆盖 `iterator()` 方法,则只能替换现有的方法,而不能实现遍历顺序的选择。
+如果现在有一个 **Iterable** 类,你想要添加一种或多种在 *for-in* 语句中使用这个类的方法,应该怎么做呢?例如,你希望可以选择正向还是反向遍历一个单词列表。如果直接继承这个类,并重写 `iterator()` 方法,则只能替换现有的方法,而不能实现遍历顺序的选择。
一种解决方案是所谓*适配器方法*(Adapter Method)的惯用法。“适配器”部分来自于设计模式,因为必须要提供特定的接口来满足 *for-in* 语句。如果已经有一个接口并且需要另一个接口时,则编写适配器就可以解决这个问题。
-在这里,若希望在默认的正向迭代器的基础上,添加产生反向迭代器的能力,因此不能使用覆盖,相反,而是添加了一个能够生成 **Iterable** 对象的方法,该对象可以用于 *for-in* 语句。这使得我们可以提供多种使用 *for-in* 语句的方式:
+在这里,若希望在默认的正向迭代器的基础上,添加产生反向迭代器的能力,因此不能使用重写,相反,而是添加了一个能够生成 **Iterable** 对象的方法,该对象可以用于 *for-in* 语句。这使得我们可以提供多种使用 *for-in* 语句的方式:
```java
// collections/AdapterMethodIdiom.java
diff --git a/docs/book/13-Functional-Programming.md b/docs/book/13-Functional-Programming.md
index 0f8b5e83..9cef7164 100644
--- a/docs/book/13-Functional-Programming.md
+++ b/docs/book/13-Functional-Programming.md
@@ -127,7 +127,7 @@ Hello there Hello there
Lambda 表达式是使用**最小可能**语法编写的函数定义:
-1. Lambda 表达式产生函数,而不是类。 在 JVM(Java Virtual Machine,Java 虚拟机)上,一切都是一个类,因此在幕后执行各种操作使 Lambda 看起来像函数 —— 但作为程序员,你可以高兴地假装它们“只是函数”。
+1. Lambda 表达式产生函数,而不是类。 虽然在 JVM(Java Virtual Machine,Java 虚拟机)上,一切都是类,但是幕后有各种操作执行让 Lambda 看起来像函数 —— 作为程序员,你可以高兴地假装它们“就是函数”。
2. Lambda 语法尽可能少,这正是为了使 Lambda 易于编写和使用。
@@ -424,7 +424,7 @@ lambda
Go::go()
```
-**Thread** 对象将 **Runnable** 作为其构造函数参数,并具有会调用 `run()` 的方法 `start()`。 **注意**,只有**匿名内部类**才需要具有名为 `run()` 的方法。
+**Thread** 对象将 **Runnable** 作为其构造函数参数,并具有会调用 `run()` 的方法 `start()`。 注意这里只有**匿名内部类**才要求显式声明 `run()` 方法。
@@ -469,11 +469,11 @@ X::f()
```
-截止目前,我们看到了与对应接口签名相同的方法引用。 在 **[1]**,我们尝试把 `X` 的 `f()` 方法引用赋值给 **MakeString**。结果即使 `make()` 与 `f()` 具有相同的签名,编译也会报“invalid method reference”(无效方法引用)错误。 这是因为实际上还有另一个隐藏的参数:我们的老朋友 `this`。 你不能在没有 `X` 对象的前提下调用 `f()`。 因此,`X :: f` 表示未绑定的方法引用,因为它尚未“绑定”到对象。
+到目前为止,我们已经见过了方法引用和对应接口的签名(参数类型和返回类型)一致的几个赋值例子。 在 **[1]** 中,我们尝试同样的做法,把 `X` 的 `f()` 方法引用赋值给 **MakeString**。结果即使 `make()` 与 `f()` 具有相同的签名,编译也会报“invalid method reference”(无效方法引用)错误。 问题在于,这里其实还需要另一个隐藏参数参与:我们的老朋友 `this`。 你不能在没有 `X` 对象的前提下调用 `f()`。 因此,`X :: f` 表示未绑定的方法引用,因为它尚未“绑定”到对象。
-要解决这个问题,我们需要一个 `X` 对象,所以我们的接口实际上需要一个额外的参数,如上例中的 **TransformX**。 如果将 `X :: f` 赋值给 **TransformX**,在 Java 中是允许的。我们必须做第二个心理调整——使用未绑定的引用时,函数式方法的签名(接口中的单个方法)不再与方法引用的签名完全匹配。 原因是:你需要一个对象来调用方法。
+要解决这个问题,我们需要一个 `X` 对象,因此我们的接口实际上需要一个额外的参数,正如在 **TransformX** 中看到的那样。 如果将 `X :: f` 赋值给 **TransformX**,在 Java 中是允许的。我们必须做第二个心理调整——使用未绑定的引用时,函数式方法的签名(接口中的单个方法)不再与方法引用的签名完全匹配。 原因是:你需要一个对象来调用方法。
-**[2]** 的结果有点像脑筋急转弯。我拿到未绑定的方法引用,并且调用它的`transform()`方法,将一个X类的对象传递给它,最后使得 `x.f()` 以某种方式被调用。Java知道它必须拿到第一个参数,该参数实际就是`this`,然后调用方法作用在它之上。
+**[2]** 的结果有点像脑筋急转弯。我拿到未绑定的方法引用,并且调用它的`transform()`方法,将一个X类的对象传递给它,最后使得 `x.f()` 以某种方式被调用。Java知道它必须拿第一个参数,该参数实际就是`this` 对象,然后对此调用方法。
如果你的方法有更多个参数,就以第一个参数接受`this`的模式来处理。
@@ -574,7 +574,7 @@ x -> x.toString()
我们清楚这里返回类型必须是 **String**,但 `x` 是什么类型呢?
-Lambda 表达式包含类型推导(编译器会自动推导出类型信息,避免了程序员显式地声明)。编译器必须能够以某种方式推导出 `x` 的类型。
+Lambda 表达式包含 *类型推导* (编译器会自动推导出类型信息,避免了程序员显式地声明)。编译器必须能够以某种方式推导出 `x` 的类型。
下面是第二个代码示例:
@@ -586,7 +586,7 @@ Lambda 表达式包含类型推导(编译器会自动推导出类型信息,
该问题也适用于方法引用。 假设你要传递 `System.out :: println` 到你正在编写的方法 ,你怎么知道传递给方法的参数的类型?
-为了解决这个问题,Java 8 引入了 `java.util.function` 包。它包含一组接口,这些接口是 Lambda 表达式和方法引用的目标类型。 每个接口只包含一个抽象方法,称为函数式方法。
+为了解决这个问题,Java 8 引入了 `java.util.function` 包。它包含一组接口,这些接口是 Lambda 表达式和方法引用的目标类型。 每个接口只包含一个抽象方法,称为 *函数式方法* 。
在编写接口时,可以使用 `@FunctionalInterface` 注解强制执行此“函数式方法”模式:
@@ -630,11 +630,11 @@ public class FunctionalAnnotation {
}
```
-`@FunctionalInterface` 注解是可选的; Java 在 `main()` 中把 **Functional** 和 **FunctionalNoAnn** 都当作函数式接口。 在 `NotFunctional` 的定义中可看到`@FunctionalInterface` 的作用:接口中如果有多个抽象方法则会产生编译期错误。
+`@FunctionalInterface` 注解是可选的; Java 会在 `main()` 中把 **Functional** 和 **FunctionalNoAnn** 都当作函数式接口来看待。 在 `NotFunctional` 的定义中可看出`@FunctionalInterface` 的作用:当接口中抽象方法多于一个时产生编译期错误。
-仔细观察在定义 `f` 和 `fna` 时发生了什么。 `Functional` 和 `FunctionalNoAnn` 定义接口,然而被赋值的只是方法 `goodbye()`。首先,这只是一个方法而不是类;其次,它甚至都不是实现了该接口的类中的方法。这是添加到Java 8中的一点小魔法:如果将方法引用或 Lambda 表达式赋值给函数式接口(类型需要匹配),Java 会适配你的赋值到目标接口。 编译器会在后台把方法引用或 Lambda 表达式包装进实现目标接口的类的实例中。
+仔细观察在定义 `f` 和 `fna` 时发生了什么。 `Functional` 和 `FunctionalNoAnn` 声明了是接口,然而被赋值的只是方法 `goodbye()`。首先,这只是一个方法而不是类;其次,它甚至都不是实现了该接口的类中的方法。这是添加到Java 8中的一点小魔法:如果将方法引用或 Lambda 表达式赋值给函数式接口(类型需要匹配),Java 会适配你的赋值到目标接口。 编译器会在后台把方法引用或 Lambda 表达式包装进实现目标接口的类的实例中。
-尽管 `FunctionalAnnotation` 确实适合 `Functional` 模型,但 Java不允许我们像`fac`定义中的那样,将 `FunctionalAnnotation` 直接赋值给 `Functional`,因为 `FunctionalAnnotation` 并没有显式地去实现 `Functional` 接口。唯一的惊喜是,Java 8 允许我们将函数赋值给接口,这样的语法更加简单漂亮。
+虽然 `FunctionalAnnotation` 确实符合 `Functional` 模型,但是 Java不允许我们像`fac`定义的那样,将 `FunctionalAnnotation` 直接赋值给 `Functional`,因为 `FunctionalAnnotation` 并没有显式地去实现 `Functional` 接口。唯一的惊喜是,Java 8 允许我们将函数赋值给接口,这样的语法更加简单漂亮。
`java.util.function` 包旨在创建一组完整的目标接口,使得我们一般情况下不需再定义自己的接口。主要因为基本类型的存在,导致预定义的接口数量有少许增加。 如果你了解命名模式,顾名思义就能知道特定接口的作用。
@@ -646,9 +646,9 @@ public class FunctionalAnnotation {
3. 如果返回值为基本类型,则用 `To` 表示,如 `ToLongFunction ` 和 `IntToLongFunction`。
-4. 如果返回值类型与参数类型一致,则是一个运算符:单个参数使用 `UnaryOperator`,两个参数使用 `BinaryOperator`。
+4. 如果返回值类型与参数类型相同,则是一个 `Operator` :单个参数使用 `UnaryOperator`,两个参数使用 `BinaryOperator`。
-5. 如果接收两个参数且返回值为布尔值,则是一个谓词(Predicate)。
+5. 如果接收参数并返回一个布尔值,则是一个 **谓词** (`Predicate`)。
6. 如果接收的两个参数类型不同,则名称中有一个 `Bi`。
@@ -661,14 +661,14 @@ public class FunctionalAnnotation {
|无参数;
返回类型任意|**Callable**
(java.util.concurrent)
`call()`|**Callable``**|
|1 参数;
无返回值|**Consumer**
`accept()`|**`Consumer`
IntConsumer
LongConsumer
DoubleConsumer**|
|2 参数 **Consumer**|**BiConsumer**
`accept()`|**`BiConsumer`**|
-|2 参数 **Consumer**;
1 引用;
1 基本类型|**Obj类型Consumer**
`accept()`|**`ObjIntConsumer`
`ObjLongConsumer`
`ObjDoubleConsumer`**|
+|2 参数 **Consumer**;
第一个参数是 引用;
第二个参数是 基本类型|**Obj类型Consumer**
`accept()`|**`ObjIntConsumer`
`ObjLongConsumer`
`ObjDoubleConsumer`**|
|1 参数;
返回类型不同|**Function**
`apply()`
**To类型** 和 **类型To类型**
`applyAs类型()`|**Function``
IntFunction``
`LongFunction`
DoubleFunction``
ToIntFunction``
`ToLongFunction`
`ToDoubleFunction`
IntToLongFunction
IntToDoubleFunction
LongToIntFunction
LongToDoubleFunction
DoubleToIntFunction
DoubleToLongFunction**|
|1 参数;
返回类型相同|**UnaryOperator**
`apply()`|**`UnaryOperator`
IntUnaryOperator
LongUnaryOperator
DoubleUnaryOperator**|
-|2 参数类型相同;
返回类型相同|**BinaryOperator**
`apply()`|**`BinaryOperator`
IntBinaryOperator
LongBinaryOperator
DoubleBinaryOperator**|
-|2 参数类型相同;
返回整型|Comparator
(java.util)
`compare()`|**`Comparator`**|
+|2 参数,类型相同;
返回类型相同|**BinaryOperator**
`apply()`|**`BinaryOperator`
IntBinaryOperator
LongBinaryOperator
DoubleBinaryOperator**|
+|2 参数,类型相同;
返回整型|Comparator
(java.util)
`compare()`|**`Comparator`**|
|2 参数;
返回布尔型|**Predicate**
`test()`|**`Predicate`
`BiPredicate`
IntPredicate
LongPredicate
DoublePredicate**|
|参数基本类型;
返回基本类型|**类型To类型Function**
`applyAs类型()`|**IntToLongFunction
IntToDoubleFunction
LongToIntFunction
LongToDoubleFunction
DoubleToIntFunction
DoubleToLongFunction**|
-|2 参数类型不同|**Bi操作**
(不同方法名)|**`BiFunction`
`BiConsumer`
`BiPredicate`
`ToIntBiFunction`
`ToLongBiFunction`
`ToDoubleBiFunction`**|
+|2 参数;
类型不同|**Bi操作**
(不同方法名)|**`BiFunction`
`BiConsumer`
`BiPredicate`
`ToIntBiFunction`
`ToLongBiFunction`
`ToDoubleBiFunction`**|
此表仅提供些常规方案。通过上表,你应该或多或少能自行推导出你所需要的函数式接口。
@@ -677,7 +677,7 @@ public class FunctionalAnnotation {
例如,为什么没有 `IntComparator`,`LongComparator` 和 `DoubleComparator` 呢?有 `BooleanSupplier` 却没有其他表示 **Boolean** 的接口;有通用的 `BiConsumer` 却没有用于 **int**,**long** 和 **double** 的 `BiConsumers` 变体(我理解他们为什么放弃这些接口)。这到底是疏忽还是有人认为其他组合使用得很少呢(他们是如何得出这个结论的)?
-你还可以看到基本类型给 Java 添加了多少复杂性。基于效率方面的考虑(问题之后有所缓解),该语言的第一版中就包含了基本类型。现在,在语言的生命周期中,我们仍然会受到语言设计选择不佳的影响。
+你还可以看到基本类型给 Java 添加了多少复杂性。该语言的第一版中就包含了基本类型,原因是考虑效率问题(该问题很快就缓解了)。现在,在语言的生命周期里,我们一直忍受语言设计的糟糕选择所带来的影响。
下面枚举了基于 Lambda 表达式的所有不同 **Function** 变体的示例:
@@ -747,9 +747,9 @@ public class FunctionVariants {
}
```
-这些 Lambda 表达式尝试生成适合函数签名的最简代码。 在某些情况下,有必要进行强制类型转换,否则编译器会报截断错误。
+这些 Lambda 表达式尝试生成适合函数签名的最简代码。 在某些情况下有必要进行强制类型转换,否则编译器会报截断错误。
-主方法中的每个测试都显示了 `Function` 接口中不同类型的 `apply()` 方法。 每个都产生一个与其关联的 Lambda 表达式的调用。
+`main()`中的每个测试都显示了 `Function` 接口中不同类型的 `apply()` 方法。 每个都产生一个与其关联的 Lambda 表达式的调用。
方法引用有自己的小魔法:
@@ -788,7 +788,7 @@ accept()
someOtherName()
```
-查看 `BiConsumer` 的文档,你会看到 `accept()` 方法。 实际上,如果我们将方法命名为 `accept()`,它就可以作为方法引用。 但是我们也可用不同的名称,比如 `someOtherName()`。只要参数类型、返回类型与 `BiConsumer` 的 `accept()` 相同即可。
+查看 `BiConsumer` 的文档,你会看到它的函数式方法为 `accept()` 。 的确,如果我们将方法命名为 `accept()`,它就可以作为方法引用。 但是我们也可用不同的名称,比如 `someOtherName()`。只要参数类型、返回类型与 `BiConsumer` 的 `accept()` 相同即可。
因此,在使用函数接口时,名称无关紧要——只要参数类型和返回类型相同。 Java 会将你的方法映射到接口方法。 要调用方法,可以调用接口的函数式方法名(在本例中为 `accept()`),而不是你的方法名。
@@ -876,7 +876,7 @@ public class TriFunctionTest {
### 缺少基本类型的函数
-让我们重温一下 `BiConsumer`,看看我们如何创建缺少的针对 **int**,**long** 和 **double** 的各种排列:
+让我们重温一下 `BiConsumer`,看看我们将如何创建各种缺失的预定义组合,涉及 **int**,**long** 和 **double** (基本类型):
```java
// functional/BiConsumerPermutations.java
@@ -908,7 +908,7 @@ public class BiConsumerPermutations {
这里使用 `System.out.format()` 来显示。它类似于 `System.out.println()` 但提供了更多的显示选项。 这里,`%f` 表示我将 `n` 作为浮点值给出,`%d` 表示 `n` 是一个整数值。 这其中可以包含空格,输入 `%n` 会换行 — 当然使用传统的 `\n` 也能换行,但 `%n` 是自动跨平台的,这是使用 `format()` 的另一个原因。
-上例简单使用了包装类型,装箱和拆箱负责它与基本类型之间的来回转换。 又比如,我们可以将包装类型和`Function`一起使用,而不去用各种针对基本类型的预定义接口。代码示例:
+上例只是简单使用了合适的包装类型,而装箱和拆箱负责它与基本类型之间的来回转换。 又比如,我们可以将包装类型和`Function`一起使用,而不去用各种针对基本类型的预定义接口。代码示例:
```java
// functional/FunctionWithWrapped.java
@@ -932,7 +932,7 @@ public interface IntToDoubleFunction {
}
```
-因为我们可以简单地写 `Function ` 并产生正常的结果,所以用基本类型的唯一原因是可以避免传递参数和返回结果过程中的自动装箱和自动拆箱,进而提升性能。
+因为我们可以简单地写 `Function ` 并产生正常的结果,所以用基本类型(`IntToDoubleFunction`)的唯一理由是可以避免传递参数和返回结果过程中的自动拆装箱,进而提升性能。
似乎是考虑到使用频率,某些函数类型并没有预定义。
@@ -1050,7 +1050,7 @@ O
**闭包**(Closure)一词总结了这些问题。 它非常重要,利用闭包可以轻松生成函数。
-考虑一个更复杂的 Lambda,它使用函数作用域之外的变量。 返回该函数会发生什么? 也就是说,当你调用函数时,它对那些 “外部 ”变量引用了什么? 如果语言不能自动解决,那问题将变得非常棘手。 能够解决这个问题的语言被称为**支持闭包**,或者叫作在词法上限定范围( 也使用术语*变量捕获* )。Java 8 提供了有限但合理的闭包支持,我们将用一些简单的例子来研究它。
+考虑一个更复杂的 Lambda,它使用函数作用域之外的变量。 返回该函数会发生什么? 也就是说,当你调用函数时,它对那些 “外部 ”变量引用了什么? 如果语言不能自动解决,那问题将变得非常棘手。 能够解决这个问题的语言被称作 *支持闭包*,或者称作 *词法定界*(*lexically scoped* ,基于词法作用域的)( 也有用术语 *变量捕获* *variable capture* 称呼的)。Java 8 提供了有限但合理的闭包支持,我们将用一些简单的例子来研究它。
首先,下列方法返回一个函数,该函数访问对象字段和方法参数:
@@ -1169,7 +1169,7 @@ public class Closure5 {
**等同 final 效果**意味着可以在变量声明前加上 **final** 关键字而不用更改任何其余代码。 实际上它就是具备 `final` 效果的,只是没有明确说明。
-通过在闭包中使用 `final` 关键字提前修饰变量 `x` 和 `i` , 我们解决了 `Closure5.java` 中的问题。代码示例:
+在闭包中,在使用 `x` 和 `i` 之前,通过将它们赋值给 `final` 修饰的变量,我们解决了 `Closure5.java` 中遇到的问题。代码示例:
```java
@@ -1191,7 +1191,7 @@ public class Closure6 {
上例中 `iFinal` 和 `xFinal` 的值在赋值后并没有改变过,因此在这里使用 `final` 是多余的。
-如果函数式方法中使用的外部局部变量是引用,而不是基本类型的话,会是什么情况呢?我们可以把`int`类型改为`Integer`类型研究一下:
+如果改用包装类型会是什么情况呢?我们可以把`int`类型改为`Integer`类型研究一下:
```java
// functional/Closure7.java
@@ -1208,7 +1208,7 @@ public class Closure7 {
}
```
-编译器非常聪明地识别到变量 `i` 的值被更改过。 因为包装类型可能被特殊处理过了,所以我们尝试下 **List**:
+编译器非常聪明地识别到变量 `i` 的值被更改过。 包装类型可能是被特殊处理了,我们再尝试下 **List**:
```java
// functional/Closure8.java
@@ -1250,7 +1250,7 @@ public class Closure8 {
请**注意**我已经声明 `ai` 是 `final` 的了。尽管在这个例子中你可以去掉 `final` 并得到相同的结果(试试吧!)。 应用于对象引用的 `final` 关键字仅表示不会重新赋值引用。 它并不代表你不能修改对象本身。
-下面我们来看看 `Closure7.java` 和 `Closure8.java` 之间的区别。我们看到:在 `Closure7.java` 中变量 `i` 有过重新赋值。 也许这就是触发**等同 final 效果**错误消息的原因。
+我们来看看 `Closure7.java` 和 `Closure8.java` 之间的区别。我们看到:在 `Closure7.java` 中变量 `i` 有过重新赋值。 也许这就是触发**等同 final 效果**错误消息的原因。
```java
// functional/Closure9.java
@@ -1270,7 +1270,7 @@ public class Closure9 {
上例,重新赋值引用会触发错误消息。如果只修改指向的对象则没问题,只要没有其他人获得对该对象的引用(这意味着你有多个实体可以修改对象,此时事情会变得非常混乱),基本上就是安全的[^6]。
-让我们回顾一下 `Closure1.java`。那么现在问题来了:为什么变量 `i` 被修改编译器却没有报错呢。 它既不是 `final` 的,也不是**等同 final 效果**的。因为 `i` 是外围类的成员,所以这样做肯定是安全的(除非你正在创建共享可变内存的多个函数)。是的,你可以辩称在这种情况下不会发生变量捕获(Variable Capture)。但可以肯定的是,`Closure3.java` 的错误消息是专门针对局部变量的。因此,规则并非只是“在 Lambda 之外定义的任何变量必须是 `final` 的或**等同 final 效果**那么简单。相反,你必须考虑捕获的变量是否是**等同 final 效果**的。 如果它是对象中的字段,那么它拥有独立的生存周期,并且不需要任何特殊的捕获,以便稍后在调用 Lambda 时存在。
+让我们回顾一下 `Closure1.java`。那么现在问题来了:为什么变量 `i` 被修改编译器却没有报错呢。 它既不是 `final` 的,也不是**等同 final 效果**的。因为 `i` 是外部类的成员,所以这样做肯定是安全的(除非你正在创建共享可变内存的多个函数)。是的,你可以辩称在这种情况下不会发生变量捕获(Variable Capture)。但可以肯定的是,`Closure3.java` 的错误消息是专门针对局部变量的。因此,规则并非只是 “在 Lambda 之外定义的任何变量必须是 `final` 的或**等同 final 效果**” 那么简单。相反,你必须考虑捕获的变量是否是**等同 final 效果**的。 如果它是对象中的字段(实例变量),那么它有独立的生命周期,不需要任何特殊的捕获以便稍后在调用 Lambda 时存在。(注:结论是——Lambda 可以没有限制地引用 实例变量和静态变量。但 局部变量必须显式声明为final,或事实上是final 。)
@@ -1302,15 +1302,15 @@ public class AnonymousClosure {
## 函数组合
-函数组合(Function Composition)意为“多个函数组合成新函数”。它通常是函数式编程的基本组成部分。在前面的 `TransformFunction.java` 类中,有一个使用 `andThen()` 的函数组合示例。一些 `java.util.function` 接口中包含支持函数组合的方法 [^7]。
+函数组合(Function Composition)意为“多个函数组合成新函数”。它通常是函数式编程的基本组成部分。在前面的 `TransformFunction.java` 类中,就有一个使用 `andThen()` 的函数组合示例。一些 `java.util.function` 接口中包含支持函数组合的方法 [^7]。
| 组合方法 | 支持接口 |
| :----- | :----- |
-| `andThen(argument)`
根据参数执行原始操作 | **Function
BiFunction
Consumer
BiConsumer
IntConsumer
LongConsumer
DoubleConsumer
UnaryOperator
IntUnaryOperator
LongUnaryOperator
DoubleUnaryOperator
BinaryOperator** |
-| `compose(argument)`
根据参数执行原始操作 | **Function
UnaryOperator
IntUnaryOperator
LongUnaryOperator
DoubleUnaryOperator** |
-| `and(argument)`
短路**逻辑与**原始谓词和参数谓词 | **Predicate
BiPredicate
IntPredicate
LongPredicate
DoublePredicate** |
-| `or(argument)`
短路**逻辑或**原始谓词和参数谓词 | **Predicate
BiPredicate
IntPredicate
LongPredicate
DoublePredicate** |
-| `negate()`
该谓词的**逻辑否**谓词| **Predicate
BiPredicate
IntPredicate
LongPredicate
DoublePredicate** |
+| `andThen(argument)`
执行原操作,再执行参数操作 | **Function
BiFunction
Consumer
BiConsumer
IntConsumer
LongConsumer
DoubleConsumer
UnaryOperator
IntUnaryOperator
LongUnaryOperator
DoubleUnaryOperator
BinaryOperator** |
+| `compose(argument)`
执行参数操作,再执行原操作 | **Function
UnaryOperator
IntUnaryOperator
LongUnaryOperator
DoubleUnaryOperator** |
+| `and(argument)`
原谓词(Predicate)和参数谓词的短路**逻辑与** | **Predicate
BiPredicate
IntPredicate
LongPredicate
DoublePredicate** |
+| `or(argument)`
原谓词和参数谓词的短路**逻辑或** | **Predicate
BiPredicate
IntPredicate
LongPredicate
DoublePredicate** |
+| `negate()`
该谓词的**逻辑非**| **Predicate
BiPredicate
IntPredicate
LongPredicate
DoublePredicate** |
下例使用了 `Function` 里的 `compose()`和 `andThen()`。代码示例:
@@ -1347,7 +1347,7 @@ _fter _ll _mbul_nces
当 `f1` 获得字符串时,它已经被`f2` 剥离了前三个字符。这是因为 `compose(f2)` 表示 `f2` 的调用发生在 `f1` 之前。
-下例是 `Predicate` 的逻辑运算演示.代码示例:
+下例是 谓词(`Predicate`) 的逻辑运算演示.代码示例:
```java
// functional/PredicateComposition.java
@@ -1376,7 +1376,7 @@ foobar
foobaz
```
-`p4` 获取到了所有谓词并组合成一个更复杂的谓词。解读:如果字符串中不包含 `bar` 且长度小于 5,或者它包含 `foo` ,则结果为 `true`。
+`p4` 获取到了所有谓词(`Predicate`)并组合成一个更复杂的谓词。解读:如果字符串中不包含 `bar` 且长度小于 5,或者它包含 `foo` ,则结果为 `true`。
正因它产生如此清晰的语法,我在主方法中采用了一些小技巧,并借用了下一章的内容。首先,我创建了一个字符串对象的流,然后将每个对象传递给 `filter()` 操作。 `filter()` 使用 `p4` 的谓词来确定对象的去留。最后我们使用 `forEach()` 将 `println` 方法引用应用在每个留存的对象上。
From 4cf57da5fca73fac66a0a4895747323ff1b72799 Mon Sep 17 00:00:00 2001
From: andyphone <792998301@qq.com>
Date: Tue, 8 Dec 2020 15:46:27 +0800
Subject: [PATCH 45/68] =?UTF-8?q?13-14=20=E4=BF=AE=E6=94=B9=E8=AF=AD?=
=?UTF-8?q?=E5=8F=A5=E6=8B=97=E5=8F=A3=E9=97=AE=E9=A2=98=20(#631)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* 1
* 2
* 没有第三种形式吧?
* 修改语句拗口问题
* 修改语句拗口问题 2
* 修改语句拗口问题 3
* 修改语句拗口问题 4
* 修改语句拗口问题 5
* 修改语句拗口问题 6
* 修改语句拗口问题 7
* 修改语句拗口问题 8
* 修改语句拗口问题 9
* 拗口问题
* 修改语句拗口问题 10
* 修改语句拗口问题 11
* 修改语句拗口问题 12
* 修改语句拗口问题 13
* 修改语句拗口问题 14
* 修改语句拗口问题 14
* 修改语句拗口问题 15
* 修改语句拗口问题 16
* 修改语句拗口问题 17
* 十三章修改语句拗口问题
* 13-14 修改语句拗口问题
* 13-14 修改语句拗口问题 2
* 13-14 修改语句拗口问题 3
* 13-14 修改语句拗口问题 4
* Update 13-Functional-Programming.md
Co-authored-by: Joe <736777445@qq.com>
---
docs/book/11-Inner-Classes.md | 2 +-
docs/book/13-Functional-Programming.md | 16 ++++-----
docs/book/14-Streams.md | 50 +++++++++++++-------------
3 files changed, 35 insertions(+), 33 deletions(-)
diff --git a/docs/book/11-Inner-Classes.md b/docs/book/11-Inner-Classes.md
index caf557e8..66d3d5a1 100755
--- a/docs/book/11-Inner-Classes.md
+++ b/docs/book/11-Inner-Classes.md
@@ -1411,7 +1411,7 @@ Anonymous inner 8
Anonymous inner 9
```
-**Counter** 返回的是序列中的下一个值。我们分别使用局部内部类和匿名内部类实现了这个功能,它们具有相同的行为和能力,既然局部内部类的名字在方法外是不可见的,那为什么我们仍然使用局部内部类而不是匿名内部类呢?唯一的理由是,我们需要一个已命名的构造器,或者需要重载构造器,而匿名内部类只能用于实例初始化。
+**Counter** 返回的是序列中的下一个值。我们分别使用局部内部类和匿名内部类实现了这个功能,它们具有相同的行为和能力,既然局部内部类的名字在方法外是不可见的,那为什么我们仍然使用局部内部类而不是匿名内部类呢?唯一的理由是,我们需要一个已命名的构造器,或者需要重载构造器,而匿名内部类只能使用实例初始化。
所以使用局部内部类而不使用匿名内部类的另一个理由就是,需要不止一个该内部类的对象。
diff --git a/docs/book/13-Functional-Programming.md b/docs/book/13-Functional-Programming.md
index 9cef7164..65f3ece4 100644
--- a/docs/book/13-Functional-Programming.md
+++ b/docs/book/13-Functional-Programming.md
@@ -1429,9 +1429,9 @@ Hup Hey
**[1]** 这一连串的箭头很巧妙。*注意*,在函数接口声明中,第二个参数是另一个函数。
-**[2]** 柯里化的目的是能够通过提供一个参数来创建一个新函数,所以现在有了一个“带参函数”和剩下的 “自由函数”(free argumnet) 。实际上,你从一个双参数函数开始,最后得到一个单参数函数。
+**[2]** 柯里化的目的是能够通过提供单个参数来创建一个新函数,所以现在有了一个“带参函数”和剩下的 “自由函数”(free argument) 。实际上,你从一个双参数函数开始,最后得到一个单参数函数。
-我们可以通过添加级别来柯里化一个三参数函数:
+我们可以通过继续添加层级来柯里化一个三参数函数:
```java
// functional/Curry3Args.java
@@ -1460,7 +1460,7 @@ public class Curry3Args {
Hi Ho Hup
```
-对于每个级别的箭头级联(Arrow-cascading),你都要在类型声明中包裹另一层 **Function**。
+对于每一级的箭头级联(Arrow-cascading),你都会在类型声明周围包裹另一个 **Function** 。
处理基本类型和装箱时,请使用适当的函数式接口:
@@ -1491,17 +1491,17 @@ public class CurriedIntAdd {
## 纯函数式编程
-即使没有函数式支持,像 C 这样的基础语言,也可以按照一定的原则编写纯函数式程序。Java 8 让函数式编程更简单,不过我们要确保一切是 `final` 的,同时你的所有方法和函数没有副作用。因为 Java 在本质上并非是不可变语言,所以编译器对我们犯的错误将无能为力。
+只要多加练习,用没有函数式支持的语言也可以写出纯函数式程序(即使是 C 这样的原始语言)。Java 8 让函数式编程更简单,不过我们要确保一切是 `final` 的,同时你的所有方法和函数没有副作用。因为 Java 在本质上并非是不可变语言,所以编译器对我们犯的错误将无能为力。
-这种情况下,我们可以借助第三方工具[^9],但使用 Scala 或 Clojure 这样的语言可能更简单。因为它们从一开始就是为保持不变性而设计的。你可以采用这些语言来编写你的 Java 项目的一部分。如果必须要用纯函数式编写,则可以用 Scala(需要遵循一些规则) 或 Clojure (遵循的规则更少)。虽然 Java 支持[并发编程](./24-Concurrent-Programming.md),但如果这是你项目的核心部分,你应该考虑在项目部分功能中使用 `Scala` 或 `Clojure` 之类的语言。
+这种情况下,我们可以借助第三方工具[^9],但使用 Scala 或 Clojure 这样的语言可能更简单。因为它们从一开始就是为保持不变性而设计的。你可以采用这些语言来编写你的 Java 项目的一部分。如果必须要用纯函数式编写,则可以用 Scala(需要一些练习) 或 Clojure (仅需更少的练习)。虽然 Java 支持[并发编程](./24-Concurrent-Programming.md),但如果这是你项目的核心部分,你应该考虑在项目部分功能中使用 `Scala` 或 `Clojure` 之类的语言。
## 本章小结
-Lambda 表达式和方法引用并没有将 Java 转换成函数式语言,而是提供了对函数式编程的支持。这对 Java 来说是一个巨大的改进。因为这允许你编写更简洁明了,易于理解的代码。在下一章中,你会看到它们在流式编程中的应用。相信你会像我一样,喜欢上流式编程。
+Lambda 表达式和方法引用并没有将 Java 转换成函数式语言,而是提供了对函数式编程的支持。这对 Java 来说是一个巨大的改进。因为这允许你编写更简洁明了,易于理解的代码。在下一章中,你会看到它们在 *流式编程(streams)* 中的应用。相信你会像我一样,喜欢上流式编程。
-这些特性满足了很多羡慕Clojure、Scala 这类更函数化语言的程序员,并且阻止了Java程序员转向那些更函数化的语言(就算不能阻止,起码提供了更好的选择)。
+这些特性满足了很大一部分的、羡慕Clojure 和 Scala 这类更函数化语言的Java程序员。阻止了他们投奔向那些语言(或者至少让他们在投奔之前做好准备)。
但是,Lambdas 和方法引用远非完美,我们永远要为 Java 设计者早期的草率决定付出代价。特别是没有泛型 Lambda,所以 Lambda 在 Java 中并非一等公民。虽然我不否认 Java 8 的巨大改进,但这意味着和许多 Java 特性一样,它终究还是会让人感觉沮丧和鸡肋。
@@ -1516,7 +1516,7 @@ Lambda 表达式和方法引用并没有将 Java 转换成函数式语言,而
[^5]: 我还没有验证过这种说法。
[^6]: 当你理解了[并发编程](./24-Concurrent-Programming.md)章节的内容,你就能明白为什么更改共享变量 “不是线程安全的” 的了。
[^7]: 接口能够支持方法的原因是它们是 Java 8 默认方法,你将在下一章中了解到。
-[^8]: 一些语言,如 Python,允许像调用其他函数一样调用组合函数。但这是 Java,所以我们做做可为之事。
+[^8]: 一些语言,如 Python,允许像调用其他函数一样调用组合函数。但这是 Java,所以我们要量力而行。
[^9]: 例如,[Immutables](https://immutables.github.io/) 和 [Mutability Detector](https://mutabilitydetector.github.io/MutabilityDetector/)。
diff --git a/docs/book/14-Streams.md b/docs/book/14-Streams.md
index ba2fd7c6..253968be 100644
--- a/docs/book/14-Streams.md
+++ b/docs/book/14-Streams.md
@@ -3,15 +3,17 @@
# 第十四章 流式编程
-> 集合优化了对象的存储,而流和对象的处理有关。
+> 集合优化了对象的存储,而流(Streams)则是关于一组组对象的处理。
-流是一系列与特定存储机制无关的元素——实际上,流并没有“存储”之说。
+流(Streams)是与任何特定存储机制无关的元素序列——实际上,我们说流是 "没有存储 "的。
-使用流,无需迭代集合中的元素,就可以从管道提取和操作元素。这些管道通常被组合在一起,形成一系列对流进行操作的管道。
+取代了在集合中迭代元素的做法,使用流即可从管道中提取元素并对其操作。这些管道通常被串联在一起形成一整套的管线,来对流进行操作。
-在大多数情况下,将对象存储在集合中是为了处理他们,因此你将会发现你将把编程的主要焦点从集合转移到了流上。流的一个核心好处是,它使得程序更加短小并且更易理解。当 Lambda 表达式和方法引用(method references)和流一起使用的时候会让人感觉自成一体。流使得 Java 8 更具吸引力。
+在大多数情况下,将对象存储在集合中就是为了处理它们,因此你会发现你把编程的主要焦点从集合转移到了流上。
-举个例子,假如你要随机展示 5 至 20 之间不重复的整数并进行排序。实际上,你的关注点首先是创建一个有序集合。围绕这个集合进行后续的操作。但是使用流式编程,你就可以简单陈述你想做什么:
+流的一个核心好处是,它使得程序更加短小并且更易理解。当 Lambda 表达式和方法引用(method references)和流一起使用的时候会让人感觉自成一体。流使得 Java 8 更具吸引力。
+
+举个例子,假如你要随机展示 5 至 20 之间不重复的整数并进行排序。你要对它们进行排序的事实,会使你首先关注选用哪个有序集合,然后围绕这个集合进行后续的操作。但是使用流式编程,你就可以简单陈述你要做什么:
```java
// streams/Randoms.java
@@ -40,11 +42,11 @@ public class Randoms {
19
```
-首先,我们给 **Random** 对象一个种子(以便程序再次运行时产生相同的输出)。`ints()` 方法产生一个流并且 `ints()` 方法有多种方式的重载 — 两个参数限定了产生的数值的边界。这将生成一个随机整数流。我们用中间流操作(intermediate stream operation) `distinct()` 使流中的整数不重复,然后使用 `limit()` 方法获取前 7 个元素。接下来使用 `sorted()` 方法排序。最终使用 `forEach()` 方法遍历输出,它根据传递给它的函数对流中的每个对象执行操作。在这里,我们传递了一个可以在控制台显示每个元素的方法引用:`System.out::println` 。
+首先,我们给 **Random** 对象一个种子值47(以便程序再次运行时产生相同的输出)。`ints()` 方法产生一个流并且 `ints()` 方法有多种方式的重载 —— 两个参数限定了产生的数值的边界。这将生成一个随机整数流。我们用 *流的中间操作*(intermediate stream operation) `distinct()` 使流中的整数不重复,然后使用 `limit()` 方法获取前 7 个元素。接下来使用 `sorted()` 方法排序。最终使用 `forEach()` 方法遍历输出,它根据传递给它的函数对流中的每个对象执行操作。在这里,我们传递了一个可以在控制台显示每个元素的方法引用:`System.out::println` 。
-注意 `Randoms.java` 中没有声明任何变量。流可以在不使用赋值或可变数据的情况下对有状态的系统建模,这非常有用。
+注意 `Randoms.java` 中没有声明任何变量。流可以在不曾使用赋值或可变数据的情况下,对有状态的系统建模,这非常有用。
-声明式编程(Declarative programming)是一种编程风格,它声明想要做什么,而非指明如何做。正如我们在函数式编程中所看到的。你会发现命令式编程的形式更难以理解。代码示例:
+*声明式编程*(Declarative programming)是一种编程风格——它声明了要做什么,而不是指明(每一步)如何做。而这正是我们在函数式编程中所看到的(编程风格)。你会注意到,命令式(Imperative)编程的形式(指明每一步如何做)会更难理解:
```java
// streams/ImperativeRandoms.java
@@ -71,9 +73,9 @@ public class ImperativeRandoms {
在 `Randoms.java` 中,我们无需定义任何变量,但在这里我们定义了 3 个变量: `rand`,`rints` 和 `r`。由于 `nextInt()` 方法没有下限的原因(其内置的下限永远为 0),这段代码实现起来更复杂。所以我们要生成额外的值来过滤小于 5 的结果。
-注意,你必须用力的研究才能弄明白`ImperativeRandoms.java`程序在干什么。而在 `Randoms.java` 中,代码直接告诉了你它正在做什么。这种语义的清晰性是使用Java 8 流式编程的重要原因之一。
+注意,你必须研究代码才能搞清楚`ImperativeRandoms.java`程序在做什么。而在 `Randoms.java` 中,代码会直接告诉你它在做什么。这种语义的清晰性是使用Java 8 流式编程的重要原因之一。
-像在 `ImperativeRandoms.java` 中那样显式地编写迭代过程的方式称为外部迭代。而在 `Randoms.java` 中,你看不到任何上述的迭代过程,所以它被称为内部迭代,这是流式编程的一个核心特征。内部迭代产生的代码可读性更强,而且能更简单的使用多核处理器。通过放弃对迭代过程的控制,可以把控制权交给并行化机制。我们将在[并发编程](24-Concurrent-Programming.md)一章中学习这部分内容。
+像在 `ImperativeRandoms.java` 中那样显式地编写迭代过程的方式称为*外部迭代(external iteration)*。而在 `Randoms.java` 中,你看不到任何上述的迭代过程,所以它被称为*内部迭代(internal iteration)*,这是流式编程的一个核心特征。内部迭代产生的代码可读性更强,而且能更简单的使用多核处理器。通过放弃对迭代过程的控制,可以把控制权交给并行化机制。我们将在[并发编程](24-Concurrent-Programming.md)一章中学习这部分内容。
另一个重要方面,流是懒加载的。这代表着它只在绝对必要时才计算。你可以将流看作“延迟列表”。由于计算延迟,流使我们能够表示非常大(甚至无限)的序列,而不需要考虑内存问题。
@@ -87,7 +89,7 @@ Java 设计者面临着这样一个难题:现存的大量类库不仅为 Java
一个大的挑战来自于使用接口的库。集合类是其中关键的一部分,因为你想把集合转为流。但是如果你将一个新方法添加到接口,那就破坏了每一个实现接口的类,因为这些类都没有实现你添加的新方法。
-Java 8 采用的解决方案是:在[接口](10-Interfaces.md)中添加被 `default`(`默认`)修饰的方法。通过这种方案,设计者们可以将流式(*stream*)方法平滑地嵌入到现有类中。流方法预置的操作几乎已满足了我们平常所有的需求。流操作的类型有三种:创建流,修改流元素(中间操作, Intermediate Operations),消费流元素(终端操作, Terminal Operations)。最后一种类型通常意味着收集流元素(通常是到集合中)。
+Java 8 采用的解决方案是:在[接口](10-Interfaces.md)中添加被 `default`(`默认`)修饰的方法。通过这种方案,设计者们可以将流式(*stream*)方法平滑地嵌入到现有类中。流方法预置的操作几乎已满足了我们平常所有的需求。流操作的类型有三种:创建流,修改流元素(中间操作, Intermediate Operations),消费流元素(终端操作, Terminal Operations)。最后一种类型通常意味着收集流元素(通常是汇入一个集合)。
下面我们来看下每种类型的流操作。
@@ -265,7 +267,7 @@ public class RandomGenerators {
为了消除冗余代码,我创建了一个泛型方法 `show(Stream stream)` (在讲解泛型之前就使用这个特性,确实有点作弊,但是回报是值得的)。类型参数 `T` 可以是任何类型,所以这个方法对 **Integer**、**Long** 和 **Double** 类型都生效。但是 **Random** 类只能生成基本类型 **int**, **long**, **double** 的流。幸运的是, `boxed()` 流操作将会自动地把基本类型包装成为对应的装箱类型,从而使得 `show()` 能够接受流。
-我们可以使用 **Random** 为任意对象集合创建 **Supplier**。如下是一个文本文件提供字符串对象的例子。
+我们可以使用 **Random** 为任意对象集合创建 **Supplier**。从文本文件提供字符串对象的例子如下。
Cheese.dat 文件内容:
@@ -321,9 +323,9 @@ public class RandomWords implements Supplier {
it shop sir the much cheese by conclusion district is
```
-在这里可以看到 `split()` 更复杂的运用。在构造器里,每一行都被 `split()` 通过方括号内的空格或其它标点符号分割。在方括号后面的 `+` 表示 `+` 前面的东西可以出现一次或者多次。
+在这里可以看到 `split()` 更复杂的运用。在构造器里,每一行都被 `split()` 通过方括号内的空格或其它标点符号分割。在方括号后面的 `+` 表示 `+` 前面的东西可以出现一次或者多次(正则表达式)。
-你会发现构造函数使用命令式编程(外部迭代)进行循环。在以后的例子中,你会看到我们是如何去除命令式编程的使用。这种旧的形式虽不是特别糟糕,但使用流会让人感觉更好。
+你会发现构造函数使用命令式编程(外部迭代)进行循环。在以后的例子中,你会看到我们是如何去除命令式编程。这种旧的形式虽不是特别糟糕,但使用流会让人感觉更好。
在`toString()` 和`main()`方法中你看到了 `collect()` 操作,它根据参数来结合所有的流元素。当你用 `Collectors.joining()`作为 `collect()` 的参数时,将得到一个`String` 类型的结果,该结果是流中的所有元素被`joining()`的参数隔开。还有很多不同的 `Collectors` 用于产生不同的结果。
@@ -365,7 +367,7 @@ public class Ranges {
在主方法中的第一种方式是我们传统编写 `for` 循环的方式;第二种方式,我们使用 `range()` 创建了流并将其转化为数组,然后在 `for-in` 代码块中使用。但是,如果你能像第三种方法那样全程使用流是更好的。我们对范围中的数字进行求和。在流中可以很方便的使用 `sum()` 操作求和。
-注意 **IntStream.**`range()` 相比 `onjava.Range.range()` 拥有更多的限制。这是由于其可选的第三个参数,后者允许步长大于 1,并且可以从大到小来生成。
+注意 **IntStream.**`range()` 相比 `onjava.Range.range()` 受更多限制。这是由于其可选的第三个参数,后者允许步长大于 1,并且可以从大到小来生成。
实用小功能 `repeat()` 可以用来替换简单的 `for` 循环。代码示例:
@@ -406,7 +408,7 @@ Hi!
Hi!
```
-原则上,在代码中包含并解释 `repeat()` 并不值得。诚然它是一个相当透明的工具,但结果取决于你的团队和公司的运作方式。
+原则上,在代码中包含和解释 `repeat()` 并不值得。诚然它是一个相当透明的工具,但这取决于你的团队和公司的运作方式。
### generate()
@@ -441,7 +443,7 @@ public class Generator implements Supplier {
YNZBRNYGCFOWZNTCQRGSEGZMMJMROE
```
-使用 `Random.nextInt()` 方法来挑选字母表中的大写字母。`Random.nextInt()` 的参数代表可以接受的最大的随机数范围,所以使用数组边界是经过深思熟虑的。
+使用 `Random.nextInt()` 方法来挑选字母表中的大写字母。`Random.nextInt()` 的参数代表可以接受的最大的随机数范围,所以使用数组边界是经过慎重考虑的。
如果要创建包含相同对象的流,只需要传递一个生成那些对象的 `lambda` 到 `generate()` 中:
@@ -513,11 +515,11 @@ Bubble(3)
Bubble(4)
```
-这是创建单独工厂类(Separate Factory class)的另一种方式。在很多方面它更加整洁,但是这是一个对于代码组织和品味的问题——你总是可以创建一个完全不同的工厂类。
+这是创建单独工厂类(Separate Factory class)的另一种方式。在很多方面它更加整洁,但是这是一个关于代码组织和品味的问题——你总是可以创建一个完全不同的工厂类。
### iterate()
-`Stream.iterate()` 产生的流的第一个元素是种子(iterate方法的第一个参数),然后将种子传递给方法(iterate方法的第二个参数)。方法运行的结果被添加到流(作为流的第二个元素),并存储起来作为下次调用 `iterate()`时的第一个参数,以此类推。我们可以利用 `iterate()` 生成一个斐波那契数列。代码示例:
+`Stream.iterate()` 产生的流的第一个元素是种子(iterate方法的第一个参数),然后将种子传递给方法(iterate方法的第二个参数)。方法运行的结果被添加到流(作为流的下一个元素),并被存储起来,作为下次调用 `iterate()`方法时的第一个参数,以此类推。我们可以利用 `iterate()` 生成一个斐波那契数列(上一章已经遇到过Fibonacci)。代码示例:
```java
// streams/Fibonacci.java
@@ -563,7 +565,7 @@ public class Fibonacci {
### 流的建造者模式
-在建造者模式(Builder design pattern)中,首先创建一个 `builder` 对象,然后将创建流所需的多个信息传递给它,最后`builder` 对象执行”创建“流的操作。**Stream** 库提供了这样的 `Builder`。在这里,我们重新审视文件读取并将其转换成为单词流的过程。代码示例:
+在*建造者模式*(Builder design pattern)中,首先创建一个 `builder` 对象,然后将创建流所需的多个信息传递给它,最后`builder` 对象执行”创建“流的操作。**Stream** 库提供了这样的 `Builder`。在这里,我们重新审视文件读取并将其转换成为单词流的过程。代码示例:
```java
// streams/FileToWordsBuilder.java
@@ -722,7 +724,7 @@ public class FileToWordsRegexp {
Not much of a cheese shop really is it
```
-在构造器中我们读取了文件中的所有内容(跳过第一行注释,并将其转化成为单行字符串)。现在,当你调用 `stream()` 的时候,可以像往常一样获取一个流,但这次你可以多次调用 `stream()` 在已存储的字符串中创建一个新的流。这里有个限制,整个文件必须存储在内存中;在大多数情况下这并不是什么问题,但是这损失了流操作非常重要的优势:
+在构造器中我们读取了文件中的所有内容(跳过第一行注释,并将其转化成为单行字符串)。现在,当你调用 `stream()` 的时候,可以像往常一样获取一个流,但这回你可以多次调用 `stream()` ,每次从已存储的字符串中创建一个新的流。这里有个限制,整个文件必须存储在内存中;在大多数情况下这并不是什么问题,但是这丢掉了流操作非常重要的优势:
1. “不需要把流存储起来。”当然,流确实需要一些内部存储,但存储的只是序列的一小部分,和存储整个序列不同。
2. 它们是懒加载计算的。
@@ -795,11 +797,11 @@ you what to the that sir leads in district And
### 移除元素
-* `distinct()`:在 `Randoms.java` 类中的 `distinct()` 可用于消除流中的重复元素。相比创建一个 **Set** 集合,该方法的工作量要少得多。
+* `distinct()`:在 `Randoms.java` 类中的 `distinct()` 可用于消除流中的重复元素。相比创建一个 **Set** 集合来消除重复,该方法的工作量要少得多。
-* `filter(Predicate)`:若元素传递给过滤函数产生的结果为`true` ,则过滤操作保留这些元素。
+* `filter(Predicate)`:过滤操作,保留如下元素:若元素传递给过滤函数产生的结果为`true` 。
-在下例中,`isPrime()` 作为过滤器函数,用于检测质数。
+在下例中,`isPrime()` 作为过滤函数,用于检测质数。
```java
// streams/Prime.java
From d05cb54eaac23a04184e3f106424339981a43b7f Mon Sep 17 00:00:00 2001
From: LingCoder <34231795+LingCoder@users.noreply.github.com>
Date: Fri, 11 Dec 2020 12:19:14 +0800
Subject: [PATCH 46/68] Update README.md
---
README.md | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index e6c333a9..9e9e83bd 100644
--- a/README.md
+++ b/README.md
@@ -3,8 +3,7 @@
## 书籍简介
- 本书原作者为 [美] Bruce Eckel,即《Java 编程思想》的作者。
-- 本书是事实上的 《Java 编程思想》第五版。
-- 《Java 编程思想》第四版基于 JAVA **5** 版本;《On Java 8》 基于 JAVA **8** 版本。
+
## 传送门
@@ -99,7 +98,7 @@
1. 本书排版布局和翻译风格上参考**阮一峰**老师的 [中文技术文档的写作规范](https://github.com/ruanyf/document-style-guide)
2. 采用第一人称叙述。
3. 由于中英行文差异,完全的逐字逐句翻译会很冗余啰嗦。所以本人在翻译过程中,去除了部分主题无关内容、重复描写。
-4. 译者在翻译中同时参考了谷歌、百度、有道翻译的译文以及《Java 编程思想》第四版中文版的部分内容(对其翻译死板,生造名词,语言精炼度差问题进行规避和改正)。最后结合译者自己的理解进行本地化,尽量做到专业和言简意赅,方便大家更好的理解学习。
+4. 译者在翻译中同时参考了谷歌、百度、有道翻译的译文。最后结合译者自己的理解进行本地化,尽量做到专业和言简意赅,方便大家更好的理解学习。
5. 由于译者个人能力、时间有限,如有翻译错误和笔误的地方,还请大家批评指正!
## 如何参与
From 4b782bedf76ea58f3359505e0a0354c6dd0b5f81 Mon Sep 17 00:00:00 2001
From: LingCoder
Date: Wed, 9 Sep 2020 23:14:24 +0800
Subject: [PATCH 47/68] =?UTF-8?q?=E7=BF=BB=E8=AF=91?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
docs/book/00-Introduction.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/book/00-Introduction.md b/docs/book/00-Introduction.md
index bcd233c0..a9ec9f27 100644
--- a/docs/book/00-Introduction.md
+++ b/docs/book/00-Introduction.md
@@ -1,7 +1,7 @@
# 简介
-> “我的语言极限,即是我的世界的极限。” ——路德维希·维特根斯坦(*Wittgenstein*)
+> “语言观决定世界观。” ——路德维希·维特根斯坦(*Wittgenstein*)
这句话无论对于自然语言还是编程语言来说都是一样的。你所使用的编程语言会将你的思维模式固化并逐渐远离其他语言,而且往往发生在潜移默化中。Java 作为一门傲娇的语言尤其如此。
From a5e6ce4b8961164f9b9d4a2e91b4ebd62f735bde Mon Sep 17 00:00:00 2001
From: LingCoder
Date: Fri, 11 Dec 2020 12:50:07 +0800
Subject: [PATCH 48/68] =?UTF-8?q?=E5=9B=A0=E4=B8=BA=E4=BE=B5=E6=9D=83?=
=?UTF-8?q?=E9=97=AE=E9=A2=98=EF=BC=8C=E5=88=A0=E9=99=A4=E4=BB=8B=E7=BB=8D?=
=?UTF-8?q?=E9=A1=B5=E4=B8=8E=E3=80=8AJava=E7=BC=96=E7=A8=8B=E6=80=9D?=
=?UTF-8?q?=E6=83=B3=E3=80=8B=E6=9C=89=E5=85=B3=E7=9A=84=E5=8F=AF=E8=83=BD?=
=?UTF-8?q?=E9=80=A0=E6=88=90=E9=94=99=E8=AF=AF=E5=BC=95=E5=AF=BC=E7=9A=84?=
=?UTF-8?q?=E6=96=87=E5=AD=97?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
docs/README.md | 4 +---
docs/_coverpage.md | 2 +-
docs/book/24-Concurrent-Programming.md | 8 ++++----
3 files changed, 6 insertions(+), 8 deletions(-)
diff --git a/docs/README.md b/docs/README.md
index fca2f067..d51ce131 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -9,8 +9,6 @@
## 书籍简介
* 本书原作者为 [美] Bruce Eckel,即《Java 编程思想》的作者。
-* 本书是事实上的 《Java 编程思想》第五版。
-* 《Java 编程思想》第四版基于 JAVA **5** 版本;《On Java 8》 基于 JAVA **8** 版本。
## 翻译说明
@@ -18,7 +16,7 @@
1. 本书排版布局和翻译风格上参考了**阮一峰**老师的 [中文技术文档的写作规范](https://github.com/ruanyf/document-style-guide)
2. 采用第一人称叙述。
3. 由于中英行文差异,完全的逐字逐句翻译会很冗余啰嗦。所以本人在翻译过程中,去除了部分主题无关内容、重复描写。
-4. 译者在翻译中同时参考了谷歌、百度、有道翻译的译文以及《Java编程思想》第四版中文版的部分内容(对其翻译死板,生造名词,语言精炼度差问题进行规避和改正)。最后结合译者自己的理解进行本地化,尽量做到专业和言简意赅,方便大家更好的理解学习。
+4. 译者在翻译中同时参考了谷歌、百度、有道翻译的译文。最后结合译者自己的理解进行本地化,尽量做到专业和言简意赅,方便大家更好的理解学习。
5. 由于译者个人能力、时间有限,如有翻译错误和笔误的地方,还请大家批评指正!
## 如何参与
diff --git a/docs/_coverpage.md b/docs/_coverpage.md
index 09ca8f43..68c3bf2f 100644
--- a/docs/_coverpage.md
+++ b/docs/_coverpage.md
@@ -2,7 +2,7 @@
# On Java 8
-- 《On Java 8》中文版,是事实上的《Java 编程思想》第5版。
+- 《On Java 8》中文版。
[](https://github.com/lingcoder/OnJava8) [](https://github.com/lingcoder/OnJava8)
diff --git a/docs/book/24-Concurrent-Programming.md b/docs/book/24-Concurrent-Programming.md
index 201b9a3d..52e7aacd 100755
--- a/docs/book/24-Concurrent-Programming.md
+++ b/docs/book/24-Concurrent-Programming.md
@@ -65,13 +65,13 @@ slowdown occurs):
- **并行-并发**:使用并行编程技术编写,如果只有一个处理器,结果程序仍然可以运行(Java 8 **Streams** 就是一个很好的例子)。
- **纯并行**:除非有多个处理器,否则不会运行。
-在某些情况下,这可能是一个有用的分类法。
+在某些情况下,这是一个有效的分类法。
-支持并发性的语言和库似乎是[抽象泄露(Leaky Abstraction)](https://en.wikipedia.org/wiki/Leaky_abstraction) 一词的完美候选。抽象的目标是“抽象出”那些对于手头想法不重要的东西,以屏蔽不必要的细节。如果抽象是有漏洞的,那些碎片和细节就会不断重新声明自己是重要的,无论你废了多少功夫来隐藏它们。
+支持并发性的语言和库似乎是[抽象泄露(Leaky Abstraction)](https://en.wikipedia.org/wiki/Leaky_abstraction) 一词的完美候选。抽象的目标是“抽象”掉那些对手头的想法不重要的部分,以屏蔽不必要的细节所带来的影响。如果抽象是有漏洞的,那么即使废很大功夫去隐藏它们,这些细枝末节也总会不断凸显出自己是重要的,。
-我开始怀疑是否真的有高度抽象。因为当编写这类程序时,底层的系统、工具,甚至是关于 CPU 缓存如何工作的细节,都永远不会被屏蔽。最后,如果你非常小心,你创作的东西在特定的情况下工作,但在其他情况下不工作。有时是两台机器的配置方式不同,有时是程序的估计负载不同。这不是 Java 特有的 - 这是并发和并行编程的本质。
+于是我开始怀疑是否真的有高度地抽象。因为当编写这类程序时,底层的系统、工具,甚至是关于 CPU 缓存如何工作的细节,都永远不会被屏蔽。最后,即使你已非常谨慎,你开发的程序也不一定在所有情况下运行正常。有时是因为两台机器的配置不同,有时是程序的预计负载不同。这不是 Java 特有的 - 这是并发和并行编程的本质。
-你可能会认为[纯函数式 ](https://en.wikipedia.org/wiki/Purely_functional) 语言没有这些限制。实际上,纯函数式语言解决了大量并发问题,所以如果你正在解决一个困难的并发问题,你可以考虑用纯函数语言编写这个部分。但最终,如果你编写一个使用队列的系统,例如,如果该系统没有被正确地调整,并且输入速率也没有被正确地估计或限制(在不同的情况下,限制意味着具有不同的影响的不同东西),该队列要么被填满并阻塞,要么溢出。最后,你必须了解所有细节,任何问题都可能会破坏你的系统。这是一种非常不同的编程方式。
+你可能会认为[纯函数式](https://en.wikipedia.org/wiki/Purely_functional) 语言没有这些限制。实际上,纯函数式语言的确解决了大量并发问题。如果你正在解决一个困难的并发问题,可以考虑用纯函数语言编写这个部分。但是,如果你编写一个使用队列的系统,例如,如果该系统没有被正确地调整,并且输入速率也没有被正确地估计或限制(在不同的情况下,限制意味着具有不同的影响的不同东西),该队列要么被填满并阻塞,要么溢出。最后,你必须了解所有细节,任何问题都可能会破坏你的系统。这是一种非常不同的编程方式。
### 并发的新定义
From 963abc9397503a9ff5763e0687196f5f399f783e Mon Sep 17 00:00:00 2001
From: LingCoder
Date: Fri, 11 Dec 2020 12:53:16 +0800
Subject: [PATCH 49/68] =?UTF-8?q?=E5=9B=A0=E4=B8=BA=E4=BE=B5=E6=9D=83?=
=?UTF-8?q?=E9=97=AE=E9=A2=98=EF=BC=8C=E5=88=A0=E9=99=A4=E4=BB=8B=E7=BB=8D?=
=?UTF-8?q?=E9=A1=B5=E4=B8=8E=E3=80=8AJava=E7=BC=96=E7=A8=8B=E6=80=9D?=
=?UTF-8?q?=E6=83=B3=E3=80=8B=E6=9C=89=E5=85=B3=E7=9A=84=E5=8F=AF=E8=83=BD?=
=?UTF-8?q?=E9=80=A0=E6=88=90=E9=94=99=E8=AF=AF=E5=BC=95=E5=AF=BC=E7=9A=84?=
=?UTF-8?q?=E6=96=87=E5=AD=97?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
book.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/book.json b/book.json
index dd18be46..36f77afe 100644
--- a/book.json
+++ b/book.json
@@ -1,7 +1,7 @@
{
"title": "《On Java 8》中文版",
"author": "LingCoder",
- "description": "根据 Bruce Eckel 大神的新书 On Java 8 翻译,可以说是事实上的 Thinking in Java 5th",
+ "description": "",
"language": "zh-hans",
"gitbook": "3.2.3",
"styles": {
From 4e513bb43d49fcdc5e46211c4d0442a29351925b Mon Sep 17 00:00:00 2001
From: huakaimay <39322023+nengquqiaoxiaoyun@users.noreply.github.com>
Date: Mon, 14 Dec 2020 15:36:11 +0800
Subject: [PATCH 50/68] =?UTF-8?q?=E5=B0=86Fruit=E6=94=B9=E4=B8=BAflist=20(?=
=?UTF-8?q?#632)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
原文:but to upcast to flist, that type is a “don’t actually care
---
docs/book/20-Generics.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/book/20-Generics.md b/docs/book/20-Generics.md
index 72263fcc..d93b82ed 100644
--- a/docs/book/20-Generics.md
+++ b/docs/book/20-Generics.md
@@ -2666,7 +2666,7 @@ public class GenericsAndCovariance {
}
```
-**flist** 的类型现在是 `List extends Fruit>`,你可以读作“一个具有任何从 **Fruit** 继承的类型的列表”。然而,这实际上并不意味着这个 **List** 将持有任何类型的 **Fruit**。通配符引用的是明确的类型,因此它意味着“某种 **flist** 引用没有指定的具体类型”。因此这个被赋值的 **List** 必须持有诸如 **Fruit** 或 **Apple** 这样的指定类型,但是为了向上转型为 **Fruit**,这个类型是什么没人在意。
+**flist** 的类型现在是 `List extends Fruit>`,你可以读作“一个具有任何从 **Fruit** 继承的类型的列表”。然而,这实际上并不意味着这个 **List** 将持有任何类型的 **Fruit**。通配符引用的是明确的类型,因此它意味着“某种 **flist** 引用没有指定的具体类型”。因此这个被赋值的 **List** 必须持有诸如 **Fruit** 或 **Apple** 这样的指定类型,但是为了向上转型为 **flist**,这个类型是什么没人在意。
**List** 必须持有一种具体的 **Fruit** 或 **Fruit** 的子类型,但是如果你不关心具体的类型是什么,那么你能对这样的 **List** 做什么呢?如果不知道 **List** 中持有的对象是什么类型,你怎能保证安全地向其中添加对象呢?就像在 **CovariantArrays.java** 中向上转型一样,你不能,除非编译器而不是运行时系统可以阻止这种操作的发生。你很快就会发现这个问题。
From 91c862c8fe45b6fdf80c06531d714ddae9b890fa Mon Sep 17 00:00:00 2001
From: Joe <736777445@qq.com>
Date: Fri, 8 Jan 2021 11:03:25 +0800
Subject: [PATCH 51/68] Update 24-Concurrent-Programming.md
---
docs/book/24-Concurrent-Programming.md | 73 ++++++++++++--------------
1 file changed, 33 insertions(+), 40 deletions(-)
diff --git a/docs/book/24-Concurrent-Programming.md b/docs/book/24-Concurrent-Programming.md
index 52e7aacd..67de4a97 100755
--- a/docs/book/24-Concurrent-Programming.md
+++ b/docs/book/24-Concurrent-Programming.md
@@ -12,39 +12,32 @@
>
> 猫咪:“你一定是疯了,否则你就不会来这儿” ——爱丽丝梦游仙境 第 6 章。
+在本章之前,我们惯用一种简单顺序的叙事方式来编程,有点类似文学中的意识流:第一件事发生了,然后是第二件,第三件……总之,我们完全掌握着事情发生的进展和顺序。如果我们将一个值设置为 5,再看时它已变成 47 的话,这就令人匪夷所思了。
-在本章之前,我们惯用一种简单顺序的叙事方式来编程,有点类似文学中的意识流:第一件事发生了,然后是第二件,第三件……总之,我们完全掌握着事情发生的进展和顺序。如果将值设置为 5,再看时它已变成 47 的话,结果就很匪夷所思了。
+现在,我们来到了陌生的并发世界,在这里这样的结果一点都不奇怪。你原来相信的一切都不再可靠。原有的规则可能生效也可能失效。更可能的是原有的规则只会在某些情况下生效。我们只有完全了解这些情况,才能决定我们处理事情的方式。
-现在,我们来到了陌生的并发世界。这样的结果一点都不奇怪,因为你原来信赖的一切都不再可靠。它可能有效,也可能无效。更可能得是,它在某些情况下会起作用,而在另一些情况下则不会。只有了解了这些情况,我们才能正确地行事。
-
-作为类比,我们正常生活是发生在经典牛顿力学中的。物体具有质量:会坠落并转移动量。电线有电阻,光直线传播。假如我们进入极小、极热、极冷、或是极大的世界(我们不能生存),这些现象就会发生变化。我们无法判断某物体是粒子还是波,光是否受到重力影响,一些物质还会变为超导体。
+比如,我们正常的生活的世界是遵循经典牛顿力学的。物体具有质量:会坠落并且转移动能。电线有电阻,光沿直线传播。假如我们进入到极小、极大、极冷或者极热(那些我们无法生存的世界),这些现象就会发生改变。我们无法判断某物体是粒子还是波,光是否受到重力影响,一些物质还会变为超导体。
假设我们处在多条故事线并行的间谍小说里,非单一意识流地叙事:第一个间谍在岩石底留下了微缩胶片。当第二个间谍来取时,胶片可能已被第三个间谍拿走。小说并没有交代此处的细节。所以直到故事结尾,我们都没搞清楚到底发生了什么。
-构建并发程序好比玩[搭积木 ](https://en.wikipedia.org/wiki/Jenga) 游戏。每拉出一块放在塔顶时都有崩塌的可能。每个积木塔和应用程序都是独一无二的,有着自己的作用。你在某个系统构建中学到的知识并不一定适用于下一个系统。
+构建并发程序好比玩[搭积木](https://en.wikipedia.org/wiki/Jenga)游戏。每拉出一块放在塔顶时都有崩塌的可能。每个积木塔和应用程序都是独一无二的,有着自己的作用。你在某个系统构建中学到的知识并不一定适用于下一个系统。
本章是对并发概念最基本的介绍。虽然我们用到了现代的 Java 8 工具来演示原理,但还远未及全面论述并发。我的目标是为你提供足够的基础知识,使你能够把握问题的复杂性和危险性,从而安全地渡过这片鲨鱼肆虐的困难水域。
-更多繁琐和底层的细节,请参阅附录:[并发底层原理 ](./Appendix-Low-Level-Concurrency.md)。要进一步深入这个领域,你还必须阅读 *Brian Goetz* 等人的 《Java Concurrency in Practice》。在撰写本文时,该书已有十多年的历史了,但它仍包含我们必须要了解和明白的知识要点。理想情况下,本章和上述附录是阅读该书的良好前提。另外,*Bill Venner* 的 《Inside the Java Virtual Machine》也很值得一看。它详细描述了 JVM 的内部工作方式,包括线程。
-
-
-
+更多繁琐和底层的细节,请参阅附录:[并发底层原理](https://github.com/LingCoder/OnJava8/blob/master/docs/book/Appendix-Low-Level-Concurrency.md)。要进一步深入这个领域,你还必须阅读 *Brian Goetz* 等人的 《Java Concurrency in Practice》。在撰写本文时,该书已有十多年的历史了,但它仍包含我们必须要了解和明白的知识要点。理想情况下,本章和上述附录是阅读该书的良好前提。另外,*Bill Venner* 的 《Inside the Java Virtual Machine》也很值得一看。它详细描述了包括线程在内的 JVM 的内部工作方式。
## 术语问题
-术语“并发”,“并行”,“多任务”,“多处理”,“多线程”,分布式系统(可能还有其他)在整个编程文献中都以多种相互冲突的方式使用,并且经常被混为一谈。
-*Brian Goetz* 在他 2016 年《从并发到并行》的演讲中指出了这一点,之后提出了合理的二分法:
+术语“并发”,“并行”,“多任务”,“多处理”,“多线程”,分布式系统(可能还有其他)在整个编程文献中都以多种相互冲突的方式使用,并且经常被混为一谈。 *Brian Goetz* 在他 2016 年《从并发到并行》的演讲中指出了这一点,之后提出了合理的区分:
- 并发是关于正确有效地控制对共享资源的访问。
-
- 并行是使用额外的资源来更快地产生结果。
这些定义很好,但是我们已有几十年混乱使用和抗拒解决此问题的历史了。一般来说,当人们使用“并发”这个词时,他们的意思是“所有的一切”。事实上,我自己也经常陷入这样的想法。在大多数书籍中,包括 *Brian Goetz* 的 《Java Concurrency in Practice》,都在标题中使用这个词。
-“并发”通常表示:不止一个任务正在执行。而“并行”几乎总是代表:不止一个任务同时执行。现在你能看到问题所在了吗?“并行”也有不止一个任务正在执行的语义在里面。区别就在于细节:究竟是怎么“执行”的。此外,还有一些场景重叠:为并行编写的程序有时在单处理器上运行,而一些并发编程系统可以利用多处理器。
+“并发”通常表示:”不止一个任务正在执行“。而“并行”几乎总是代表:”不止一个任务同时执行“。现在我们能立即看出这些定义中的问题所在:“并行”也有不止一个任务正在执行的语义在里面。区别就在于细节:究竟是怎么“执行”的。此外还有一些重叠:为并行编写的程序依旧可以在单处理器上运行,而并发编写的系统也可以利用多个处理器。
-还有另一种方法,在减速发生的地方写下定义(原文 Here’s another approach, writing the definitions around where the
-slowdown occurs):
+还有另一种方式,围绕”缓慢“出现的情况写下定义:
**并发**
@@ -60,37 +53,37 @@ slowdown occurs):
我们甚至可以尝试以更细的粒度去进行定义(然而这并不是标准化的术语):
-- **纯并发**:仍然在单个 CPU 上运行任务。纯并发系统比顺序系统更快地产生结果,但是它的运行速度不会因为处理器的增加而变得更快。
-- **并发-并行**:使用并发技术,结果程序可以利用更多处理器更快地产生结果。
-- **并行-并发**:使用并行编程技术编写,如果只有一个处理器,结果程序仍然可以运行(Java 8 **Streams** 就是一个很好的例子)。
-- **纯并行**:除非有多个处理器,否则不会运行。
+- **纯并发**:仍然在单个 CPU 上运行任务。纯并发系统比时序系统更快地产生结果,但是它的运行速度不会因为处理器的增加而变得更快。
+
+- **并发-并行**:使用并发技术,结果程序可以利用多处理器更快地产生结果。
+- **并行-并发**:使用并行编程技术编写,即使只有一个处理器,结果程序仍然可以运行(Java 8 **Streams** 就是一个很好的例子)。
+- **纯并行**:只有多个处理器的情况下才能运行。
在某些情况下,这是一个有效的分类法。
-支持并发性的语言和库似乎是[抽象泄露(Leaky Abstraction)](https://en.wikipedia.org/wiki/Leaky_abstraction) 一词的完美候选。抽象的目标是“抽象”掉那些对手头的想法不重要的部分,以屏蔽不必要的细节所带来的影响。如果抽象是有漏洞的,那么即使废很大功夫去隐藏它们,这些细枝末节也总会不断凸显出自己是重要的,。
+支持并发性的语言和库似乎是[抽象泄露(Leaky Abstraction](https://en.wikipedia.org/wiki/Leaky_abstraction)一词的完美候选。抽象的目标是“抽象”掉那些对手头的想法不重要的部分,以屏蔽不必要的细节所带来的影响。如果抽象发生泄露,那么即使费很大功夫去隐藏它们,这些细枝末节也总会不断凸显出自己是重要的。
于是我开始怀疑是否真的有高度地抽象。因为当编写这类程序时,底层的系统、工具,甚至是关于 CPU 缓存如何工作的细节,都永远不会被屏蔽。最后,即使你已非常谨慎,你开发的程序也不一定在所有情况下运行正常。有时是因为两台机器的配置不同,有时是程序的预计负载不同。这不是 Java 特有的 - 这是并发和并行编程的本质。
-你可能会认为[纯函数式](https://en.wikipedia.org/wiki/Purely_functional) 语言没有这些限制。实际上,纯函数式语言的确解决了大量并发问题。如果你正在解决一个困难的并发问题,可以考虑用纯函数语言编写这个部分。但是,如果你编写一个使用队列的系统,例如,如果该系统没有被正确地调整,并且输入速率也没有被正确地估计或限制(在不同的情况下,限制意味着具有不同的影响的不同东西),该队列要么被填满并阻塞,要么溢出。最后,你必须了解所有细节,任何问题都可能会破坏你的系统。这是一种非常不同的编程方式。
+你可能会认为[纯函数式](https://en.wikipedia.org/wiki/Purely_functional)语言没有这些限制。实际上,纯函数式语言的确解决了大量并发问题。如果你正在解决一个困难的并发问题,可以考虑用纯函数语言编写这个部分。但是,如果你编写一个使用队列的系统,例如,如果该系统没有被合理地调优,并且输入速率也没有被正确地估计或限制(在不同的情况下,限制意味着具有不同的影响的不同东西),该队列要么被填满并阻塞,要么溢出。最后,你必须了解所有可能会破坏你的系统的细节和问题。这是一种非常不同的编程方式。
+
+## 并发的新定义
-
-### 并发的新定义
+几十年来,我一直在努力解决各种形式的并发问题,其中一个最大的挑战是简洁的定义它。在撰写本章的过程中,我终于有了这样的洞察力,我将其定义为:
-几十年来,我一直在努力解决各种形式的并发问题,其中一个最大的挑战一直是简单地定义它。在撰写本章的过程中,我终于有了这样的洞察力,我认为可以定义它:
->** 并发性是一系列性能技术,专注于减少等待**
+> 并发性是一系列专注于减少等待的性能技术
这实际上是一个相当复杂的表述,所以我将其分解:
-- 这是一个集合:包含许多不同的方法来解决这个问题。这是使定义并发性如此具有挑战性的问题之一,因为技术差异很大。
-- 这些是性能技术:就是这样。并发的关键点在于让你的程序运行得更快。在 Java 中,并发是非常棘手和困难的,所以绝对不要使用它,除非你有一个重大的性能问题 - 即使这样,使用最简单的方法产生你需要的性能,因为并发很快变得无法管理。
-- “减少等待”部分很重要而且微妙。无论(例如)你运行多少个处理器,你只能在等待发生时产生效益。如果你发起 I/O 请求并立即获得结果,没有延迟,因此无需改进。如果你在多个处理器上运行多个任务,并且每个处理器都以满容量运行,并且没有任务需要等待其他任务,那么尝试提高吞吐量是没有意义的。并发的唯一机会是如果程序的某些部分被迫等待。等待可以以多种形式出现 - 这解释了为什么存在如此不同的并发方法。
+- 这是一个集合:包含许多不同的方法来解决这个问题。因为技术差异很大,这是使定义并发性如此具有挑战性的问题之一。
+- 这些是性能技术:就是这样。并发的关键点在于让你的程序运行得更快。在 Java 中,并发是非常棘手和困难的,所以绝对不要使用它,除非你有一个重大的性能问题 - 即使这样,使用最简单的方法产生你需要的性能,因为并发很快变得难以管理。
+- “减少等待”部分很重要而且微妙。无论(例如)你的程序运行在多少个处理器上,你只能在等待发生时产生效益。如果你发起 I/O 请求并立即获得结果,没有延迟,因此无需改进。如果你在多个处理器上运行多个任务,并且每个处理器都以满容量运行,并且没有任务需要等待其他任务,那么尝试提高吞吐量是没有意义的。并发的唯一机会是程序的某些部分被迫等待。等待会以多种形式出现 - 这解释了为什么存在多种不同的并发方法。
值得强调的是,这个定义的有效性取决于“等待”这个词。如果没有什么可以等待,那就没有机会去加速。如果有什么东西在等待,那么就会有很多方法可以加快速度,这取决于多种因素,包括系统运行的配置,你要解决的问题类型以及其他许多问题。
-
## 并发的超能力
-想象一下,你置身于一部科幻电影。你必须在一栋大楼中找到一个东西,它被小心而巧妙地隐藏在大楼一千万个房间中的一间。你进入大楼,沿着走廊走下去。走廊是分开的。
+想象一下,你置身于一部科幻电影。你必须在一栋大楼中找到一个东西,它被小心而巧妙地隐藏在大楼千万个房间中的一间。你进入大楼,沿着走廊走下去。走廊是分开的。
一个人完成这项任务要花上一百辈子的时间。
@@ -100,31 +93,31 @@ slowdown occurs):
一旦克隆体进入房间,它必须搜索房间的每个角落。这时它切换到了第二种超能力。它分裂成了一百万个纳米机器人,每个机器人都会飞到或爬到房间里一些看不见的地方。你不需要了解这种功能 - 一旦你开启它就会自动工作。在他们自己的控制下,纳米机器人开始行动,搜索房间然后回来重新组装成你,突然间,不知怎么的,你就知道这间房间里有没有那个东西。
-我很想说,“并发就是刚才描述的置身于科幻电影中的超能力“就像你自己可以一分为二然后解决更多的问题一样简单。但是问题在于,我们来描述这种现象的任何模型最终都是泄漏抽象的(leaky abstraction)。
+我很想说,“并发就是刚才描述的置身于科幻电影中的超能力“。就像你自己可以一分为二然后解决更多的问题一样简单。但是问题在于,我们来描述这种现象的任何模型最终都是抽象泄露的(leaky abstraction)。
-以下是其中一个漏洞:在理想的世界中,每次克隆自己时,还需要复制一个物理处理器来运行该克隆。这当然是不现实的——实际上,你的机器上一般只有 4 个或 8 个处理器核心(编写本文时的典型情况)。你也可能更多,但仍有很多情况下只有一个单核处理器。在关于抽象的讨论中,分配物理处理器核心这本身就是抽象的泄露,甚至也可以支配你的决策。
+以下是其中一个泄露:在理想的世界中,每次克隆自己时,也会复制一个物理处理器来运行克隆搜索者。这当然是不现实的——实际上,你的机器上一般只有 4 个或 8 个处理器核心(编写本文时的典型情况)。或许你拥有更多的处理器,但仍有很多情况下只有一个单核处理器。在关于抽象的讨论中,分配物理处理器核心这本身就是抽象的泄露,甚至也可以支配你的决策。
让我们在科幻电影中改变一些东西。现在当每个克隆搜索者最终到达一扇门时,他们必须敲门并等到有人开门。如果每个搜索者都有一个处理器核心,这没有问题——只是空闲等待直到有人开门。但是如果我们只有 8 个处理器核心却有几千个搜索者,我们不希望处理器仅仅因为某个搜索者恰好在等待回答中被锁住而闲置下来。相反,我们希望将处理器应用于可以真正执行工作的搜索者身上,因此需要将处理器从一个任务切换到另一个任务的机制。
-许多模型能够有效地隐藏处理器的数量,允许你假装有很多个处理器。但在某些情况下,这种方法会失效,这时你必须知道处理器核心的真实数量,以便处理这个问题。
+许多模型能够有效地隐藏处理器的数量,允许你假装有很多个处理器。但在某些情况下,当你必须明确知道处理器数量以便于工作的时候,这些模型就会失效。
-最大的影响之一取决于您是使用单核处理器还是多核处理器。如果你只有单核处理器,那么任务切换的成本也由该核心承担,将并发技术应用于你的系统会使它运行得更慢。
+最大的影响之一取决于是使用单核处理器还是多核处理器。如果你只有单核处理器,那么任务切换的成本也由该核心承担,将并发技术应用于你的系统会使它运行得更慢。
这可能会让你以为,在单核处理器的情况下,编写并发代码是没有意义的。然而,有些情况下,并发模型会产生更简单的代码,光是为了这个目的就值得舍弃一些性能。
-在克隆体敲门等待的情况下,即使单核处理器系统也能从并发中受益,因为它可以从等待(阻塞)的任务切换到准备运行的任务。但是如果所有任务都可以一直运行那么切换的成本反而会使任务变慢,在这种情况下,如果你有多个进程,并发通常只会有意义。
+在克隆体敲门等待的情况下,即使单核处理器系统也能从并发中受益,因为它可以从等待(阻塞)的任务切换到准备运行的任务。但是如果所有任务都可以一直运行那么切换的成本反而会使任务变慢,在这种情况下,并发只在如果你有多个处理器的情况下有意义。
-如果你正在尝试破解某种密码,在同一时间内参与破解的线程越多,你越快得到答案的可能性就越大。每个线程都能持续使用你所分配的处理器时间,在这种情况下(CPU 密集型问题),你代码中的线程数应该和你拥有的处理器的核心数保持一致。
+假设你正在尝试破解某种密码,在同一时间内参与破解的线程越多,你越快得到答案的可能性就越大。每个线程都能持续使用你所分配的处理器时间,在这种情况下(CPU 密集型问题),你代码中的线程数应该和你拥有的处理器的核心数保持一致。
-在接听电话的客户服务部门,你只有一定数量的员工,但是你的部门可能会打来很多电话。这些员工(处理器)一次只能接听一个电话直到打完,此时其它打来的电话必须排队等待。
+在接听电话的客户服务部门,你只有一定数量的员工,但是你的部门可能会收到很多电话。这些员工(处理器)一次只能接听一个电话直到打完,此时其它打来的电话必须排队等待。
在“鞋匠和精灵”的童话故事中,鞋匠有很多工作要做,当他睡着时,出现了一群精灵来为他制作鞋子。这里的工作是分布式的,但即使使用大量的物理处理器,在制造鞋子的某些部件时也会产生限制——例如,如果鞋底的制作时间最长,这就限制了鞋子的制作速度,这也会改变你设计解决方案的方式。
-因此,你要解决的问题推动了解决方案的设计。将一个问题分解成“独立运行”的子任务,这是一种美好的抽象,然后就是残酷的现实:物理现实不断地侵入和动摇这个抽象。
+因此,你要解决的问题驱动了方案的设计。将一个问题分解成“独立运行”的子任务,这是一种美好的抽象,然后就是实际发生的现实:物理现实不断干扰和动摇这个抽象。
-这只是问题的一部分:考虑一个制作蛋糕的工厂。我们以某种方式把制作蛋糕的任务分给了工人们,但是现在是时候让工人把蛋糕放在盒子里了。那里有一个盒子,准备存放蛋糕。但是在工人把蛋糕放进盒子之前,另一个工人就冲过去,把蛋糕放进盒子里,砰!这两个蛋糕撞到一起砸坏了。这是常见的“共享内存”问题,会产生所谓的竞态条件(race condition),其结果取决于哪个工人能先把蛋糕放进盒子里(通常使用锁机制来解决问题,因此一个工作人员可以先抓住一个盒子并防止蛋糕被砸烂)。
+这只是问题的一部分:考虑一个制作蛋糕的工厂。我们以某种方式把制作蛋糕的任务分给了工人们,现在是时候让工人把蛋糕放在盒子里了。那里有一个准备存放蛋糕的盒子。但是在一个工人把蛋糕放进盒子之前,另一个工人就冲过去,把蛋糕放进盒子里,砰!这两个蛋糕撞到一起砸坏了。这是常见的“共享内存”问题,会产生所谓的竞态条件(race condition),其结果取决于哪个工人能先把蛋糕放进盒子里(通常使用锁机制来解决问题,因此一个工作人员可以先抓住一个盒子并防止蛋糕被砸烂)。
-当“同时”执行的任务相互干扰时,就会出现问题。这可能以一种微妙而偶然的方式发生,因此可以说并发是“可以论证的确定性,但实际上是不确定性的”。也就是说,假设你很小心地编写并发程序,而且通过了代码检查可以正确运行。然而实际上,我们编写的并发程序大部分情况下都能正常运行,但是在一些情况下会失败。这些情况可能永远不会发生,或者在你在测试期间几乎很难发现它们。实际上,编写测试代码通常无法为并发程序生成故障条件。由此产生的失败只会偶尔发生,因此它们以客户投诉的形式出现。这是学习并发中最强有力的论点之一:如果你忽略它,你可能会受伤。
+当“同时”执行的任务相互干扰时,就会出现问题。这可能以一种微妙而偶然的方式发生,因此可以说并发是“可以论证的确定性,但实际上是不确定性的”。也就是说,假设你很小心地编写并发程序,而且通过了代码检查可以正确运行。然而实际上,我们编写的并发程序大部分情况下都能正常运行,但是在一些特定情况下会失败。这些情况可能永远不会发生,或者在你在测试期间几乎很难发现它们。实际上,编写测试代码通常无法为并发程序生成故障条件。由此产生的失败只会偶尔发生,因此它们以客户投诉的形式出现。这是学习并发中最强有力的论点之一:如果你忽略它,你可能会受伤。
因此,并发似乎充满了危险,如果这让你有点害怕,这可能是一件好事。尽管 Java 8 在并发性方面做出了很大改进,但仍然没有像编译时验证 (compile-time verification) 或受检查的异常 (checked exceptions) 那样的安全网来告诉你何时出现错误。关于并发,你只能依靠自己,只有知识渊博、保持怀疑和积极进取的人,才能用 Java 编写可靠的并发代码。
From 21413cb09665f87e566e9e0840b0804ab7a817d4 Mon Sep 17 00:00:00 2001
From: iao113
Date: Mon, 11 Jan 2021 17:14:45 +0800
Subject: [PATCH 52/68] Update 04-Operators.md (#638)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
“内存溢出”通常指“堆栈溢出”,算术导致的溢出通常会用“数据溢出”或者“算术溢出”。
---
docs/book/04-Operators.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/book/04-Operators.md b/docs/book/04-Operators.md
index 40ae0a9f..14f8fcf7 100644
--- a/docs/book/04-Operators.md
+++ b/docs/book/04-Operators.md
@@ -1436,7 +1436,7 @@ public class AllOps {
```java
// operators/Overflow.java
-// 厉害了!内存溢出
+// 厉害了!数据溢出了!
public class Overflow {
public static void main(String[] args) {
int big = Integer.MAX_VALUE;
From a7244b24d20afe78f23d2c932f7279dd8eb0ee81 Mon Sep 17 00:00:00 2001
From: iao113
Date: Wed, 13 Jan 2021 14:21:56 +0800
Subject: [PATCH 53/68] Update 06-Housekeeping.md (#639)
typo
---
docs/book/06-Housekeeping.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/book/06-Housekeeping.md b/docs/book/06-Housekeeping.md
index 0248808c..db3510bf 100644
--- a/docs/book/06-Housekeeping.md
+++ b/docs/book/06-Housekeeping.md
@@ -1130,7 +1130,7 @@ public class ExplicitStatic {
输出:
```
-Inside main
+Inside main()
Cup(1)
Cup(2)
f(99)
@@ -1182,7 +1182,7 @@ public class Mugs {
输出:
```
-Inside main
+Inside main()
Mug(1)
Mug(2)
mug1 & mug2 initialized
From 4cef49d2a28ae6c5a1b64ccfb969c47d8be28495 Mon Sep 17 00:00:00 2001
From: iao113
Date: Fri, 29 Jan 2021 10:45:07 +0800
Subject: [PATCH 54/68] Update 07-Implementation-Hiding.md (#641)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
一些加重左右缺少空格导致显示不正确。
---
docs/book/07-Implementation-Hiding.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/docs/book/07-Implementation-Hiding.md b/docs/book/07-Implementation-Hiding.md
index 874ba9ce..946b77f7 100644
--- a/docs/book/07-Implementation-Hiding.md
+++ b/docs/book/07-Implementation-Hiding.md
@@ -61,7 +61,7 @@ import java.util.*
### 代码组织
-当编译一个 **.java** 文件时,**.java** 文件的每个类都会有一个输出文件。每个输出的文件名和 **.java** 文件中每个类的类名相同,只是后缀名是 **.class**。因此,在编译少量的 **.java** 文件后,会得到大量的 **.class** 文件。如果你使用过编译型语言,那么你可能习惯编译后产生一个中间文件(通常称为“obj”文件),然后与使用链接器(创建可执行文件)或类库生成器(创建类库)产生的其他同类文件打包到一起的情况。这不是 Java 工作的方式。在 Java 中,可运行程序是一组 **.class** 文件,它们可以打包压缩成一个 Java 文档文件(JAR,使用 **jar** 文档生成器)。Java 解释器负责查找、加载和解释这些文件。
+当编译一个 **.java** 文件时, **.java** 文件的每个类都会有一个输出文件。每个输出的文件名和 **.java** 文件中每个类的类名相同,只是后缀名是 **.class**。因此,在编译少量的 **.java** 文件后,会得到大量的 **.class** 文件。如果你使用过编译型语言,那么你可能习惯编译后产生一个中间文件(通常称为“obj”文件),然后与使用链接器(创建可执行文件)或类库生成器(创建类库)产生的其他同类文件打包到一起的情况。这不是 Java 工作的方式。在 Java 中,可运行程序是一组 **.class** 文件,它们可以打包压缩成一个 Java 文档文件(JAR,使用 **jar** 文档生成器)。Java 解释器负责查找、加载和解释这些文件。
类库是一组类文件。每个源文件通常都含有一个 **public** 类和任意数量的非 **public** 类,因此每个文件都有一个 **public** 组件。如果把这些组件集中在一起,就需要使用关键字 **package**。
@@ -327,7 +327,7 @@ public class Cookie {
}
```
-记住,**Cookie.java** 文件产生的类文件必须位于名为 **dessert** 的子目录中,该子目录在 **hiding** (表明本书的"封装"章节)下,它必须在 CLASSPATH 的几个目录之下。不要错误地认为 Java 总是会将当前目录视作查找行为的起点之一。如果你的 CLASSPATH 中没有 **.**,Java 就不会查找当前目录。
+记住,**Cookie.java** 文件产生的类文件必须位于名为 **dessert** 的子目录中,该子目录在 **hiding** (表明本书的"封装"章节)下,它必须在 CLASSPATH 的几个目录之下。不要错误地认为 Java 总是会将当前目录视作查找行为的起点之一。如果你的 CLASSPATH 中没有 **.** ,Java 就不会查找当前目录。
现在,使用 **Cookie** 创建一个程序:
```java
@@ -384,7 +384,7 @@ class Pie {
}
```
-最初看上去这两个文件毫不相关,但在 **Cake** 中可以创建一个 **Pie** 对象并调用它的 `f()` 方法。(注意,你的 CLASSPATH 中一定得有 **.**,这样文件才能编译)通常会认为 **Pie** 和 `f()` 具有包访问权限,因此不能被 **Cake** 访问。它们的确具有包访问权限,这是部分正确。**Cake.java** 可以访问它们是因为它们在相同的目录中且没有给自己设定明确的包名。Java 把这样的文件看作是隶属于该目录的默认包中,因此它们为该目录中所有的其他文件都提供了包访问权限。
+最初看上去这两个文件毫不相关,但在 **Cake** 中可以创建一个 **Pie** 对象并调用它的 `f()` 方法。(注意,你的 CLASSPATH 中一定得有 **.** ,这样文件才能编译)通常会认为 **Pie** 和 `f()` 具有包访问权限,因此不能被 **Cake** 访问。它们的确具有包访问权限,这是部分正确。**Cake.java** 可以访问它们是因为它们在相同的目录中且没有给自己设定明确的包名。Java 把这样的文件看作是隶属于该目录的默认包中,因此它们为该目录中所有的其他文件都提供了包访问权限。
### private: 你无法访问
From cf914264c6f46ba90448d399b496e17f551ab9c6 Mon Sep 17 00:00:00 2001
From: Joe <736777445@qq.com>
Date: Sat, 30 Jan 2021 19:24:21 +0800
Subject: [PATCH 55/68] Update 02-Installing-Java-and-the-Book-Examples.md
(#643)
#642
---
docs/book/02-Installing-Java-and-the-Book-Examples.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/book/02-Installing-Java-and-the-Book-Examples.md b/docs/book/02-Installing-Java-and-the-Book-Examples.md
index 86f76082..e3350b02 100644
--- a/docs/book/02-Installing-Java-and-the-Book-Examples.md
+++ b/docs/book/02-Installing-Java-and-the-Book-Examples.md
@@ -111,7 +111,7 @@ Mac 系统自带的 Java 版本太老,为了确保本书的代码示例能被
2. 在命令行下执行下面的命令来安装 Java。
```bash
- brew cask install java
+ brew install java --cask
```
当以上安装都完成后,如果你有需要,可以使用游客账户来运行本书中的代码示例。
From 20f73ef6ade215fb7b1e15159b79f9fa924dafdc Mon Sep 17 00:00:00 2001
From: Joe <736777445@qq.com>
Date: Sat, 30 Jan 2021 19:31:18 +0800
Subject: [PATCH 56/68] Update 02-Installing-Java-and-the-Book-Examples.md
---
docs/book/02-Installing-Java-and-the-Book-Examples.md | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/docs/book/02-Installing-Java-and-the-Book-Examples.md b/docs/book/02-Installing-Java-and-the-Book-Examples.md
index e3350b02..8de3ce6b 100644
--- a/docs/book/02-Installing-Java-and-the-Book-Examples.md
+++ b/docs/book/02-Installing-Java-and-the-Book-Examples.md
@@ -111,9 +111,11 @@ Mac 系统自带的 Java 版本太老,为了确保本书的代码示例能被
2. 在命令行下执行下面的命令来安装 Java。
```bash
- brew install java --cask
+ brew install --cask java
```
+> 译者注:原有命令为 `brew cask install java`。原有命令已经被禁用。具体内容可看 https://github.com/LingCoder/OnJava8/issues/642
+
当以上安装都完成后,如果你有需要,可以使用游客账户来运行本书中的代码示例。
**Linux**
From 482bb3b0856cd6ea1e67e2da9e50048889830237 Mon Sep 17 00:00:00 2001
From: iao113
Date: Sat, 30 Jan 2021 22:00:57 +0800
Subject: [PATCH 57/68] Update 08-Reuse.md (#644)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Markdown格式有误,程序输出typo
---
docs/book/08-Reuse.md | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/docs/book/08-Reuse.md b/docs/book/08-Reuse.md
index cf27c665..a2e6bc4b 100644
--- a/docs/book/08-Reuse.md
+++ b/docs/book/08-Reuse.md
@@ -68,7 +68,7 @@ i = 0 f = 0.0 source = Constructed
```
-这两个类中定义的一个方法是特殊的: `toString()`。每个非基本类型对象都有一个 `toString()` 方法,在编译器需要字符串但它有对象的特殊情况下调用该方法。因此,在 [1] 中,编译器看到你试图“添加”一个 **WaterSource** 类型的字符串对象 。因为字符串只能拼接另一个字符串,所以它就先会调用 `toString()` 将 **source** 转换成一个字符串。然后,它可以拼接这两个字符串并将结果字符串传递给 `System.out.println()`。要对创建的任何类允许这种行为,只需要编写一个 **toString()** 方法。在 `toString()` 上使用 **@Override** 注解来告诉编译器,以确保正确地覆盖。**@Override** 是可选的,但它有助于验证你没有拼写错误 (或者更微妙地说,大小写字母输入错误)。类中的基本类型字段自动初始化为零,正如 **object Everywhere** 一章中所述。但是对象引用被初始化为 **null**,如果你尝试调用其任何一个方法,你将得到一个异常(一个运行时错误)。方便的是,打印 **null** 引用却不会得到异常。
+这两个类中定义的一个方法是特殊的: `toString()`。每个非基本类型对象都有一个 `toString()` 方法,在编译器需要字符串但它有对象的特殊情况下调用该方法。因此,在 [1] 中,编译器看到你试图“添加”一个 **WaterSource** 类型的字符串对象 。因为字符串只能拼接另一个字符串,所以它就先会调用 `toString()` 将 **source** 转换成一个字符串。然后,它可以拼接这两个字符串并将结果字符串传递给 `System.out.println()`。要对创建的任何类允许这种行为,只需要编写一个 **toString()** 方法。在 `toString()` 上使用 **@Override** 注解来告诉编译器,以确保正确地覆盖。 **@Override** 是可选的,但它有助于验证你没有拼写错误 (或者更微妙地说,大小写字母输入错误)。类中的基本类型字段自动初始化为零,正如 **object Everywhere** 一章中所述。但是对象引用被初始化为 **null**,如果你尝试调用其任何一个方法,你将得到一个异常(一个运行时错误)。方便的是,打印 **null** 引用却不会得到异常。
编译器不会为每个引用创建一个默认对象,这是有意义的,因为在许多情况下,这会导致不必要的开销。初始化引用有四种方法:
@@ -200,8 +200,7 @@ public class Detergent extends Cleanser {
}
}
/* Output:
-Cleanser dilute() apply() Detergent.scrub() scrub()
-foam()
+Cleanser dilute() apply() Detergent.scrub() scrub() foam()
Testing base class:
Cleanser dilute() apply() scrub()
*/
From f47dcab808918c4a81ab199ac8295bcd46c32df2 Mon Sep 17 00:00:00 2001
From: iao113
Date: Mon, 1 Feb 2021 18:00:33 +0800
Subject: [PATCH 58/68] Update 09-Polymorphism.md (#645)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Markdown语法有误
---
docs/book/09-Polymorphism.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/book/09-Polymorphism.md b/docs/book/09-Polymorphism.md
index ddca482d..67f50ed0 100644
--- a/docs/book/09-Polymorphism.md
+++ b/docs/book/09-Polymorphism.md
@@ -503,7 +503,7 @@ class Derived extends PrivateOverride {
private f()
```
-你可能期望输出是 **public f()**,然而 **private** 方法可以当作是 **final** 的,对于派生类来说是隐蔽的。因此,这里 **Derived** 的 `f()` 是一个全新的方法;因为基类版本的 `f()` 屏蔽了 **Derived** ,因此它都不算是重写方法。
+你可能期望输出是 **public f()** ,然而 **private** 方法可以当作是 **final** 的,对于派生类来说是隐蔽的。因此,这里 **Derived** 的 `f()` 是一个全新的方法;因为基类版本的 `f()` 屏蔽了 **Derived** ,因此它都不算是重写方法。
结论是只有非 **private** 方法才能被重写,但是得小心重写 **private** 方法的现象,编译器不报错,但不会按我们所预期的执行。为了清晰起见,派生类中的方法名采用与基类中 **private** 方法名不同的命名。
@@ -1236,7 +1236,7 @@ at RTTI.main
正如前面类图所示,**MoreUseful** 扩展了 **Useful** 的接口。而 **MoreUseful** 也继承了 **Useful**,所以它可以向上转型为 **Useful**。在 `main()` 方法中可以看到这种情况的发生。因为两个对象都是 **Useful** 类型,所以对它们都可以调用 `f()` 和 `g()` 方法。如果试图调用 `u()` 方法(只存在于 **MoreUseful** 中),就会得到编译时错误信息。
-为了访问 **MoreUseful** 对象的扩展接口,就得尝试向下转型。如果转型为正确的类型,就转型成功。否则,就会得到 ClassCastException 异常。你不必为这个异常编写任何特殊代码,因为它指出了程序员在程序的任何地方都可能犯的错误。**{ThrowsException}** 注释标签告知本书的构建系统:在运行程序时,预期抛出一个异常。
+为了访问 **MoreUseful** 对象的扩展接口,就得尝试向下转型。如果转型为正确的类型,就转型成功。否则,就会得到 ClassCastException 异常。你不必为这个异常编写任何特殊代码,因为它指出了程序员在程序的任何地方都可能犯的错误。 **{ThrowsException}** 注释标签告知本书的构建系统:在运行程序时,预期抛出一个异常。
RTTI 不仅仅包括简单的转型。例如,它还提供了一种方法,使你可以在试图向下转型前检查所要处理的类型。“类型信息”一章中会详细阐述运行时类型信息的方方面面。
From c0cc40224023627a51d9d03f7e8988fe8fee9f85 Mon Sep 17 00:00:00 2001
From: iao113
Date: Fri, 5 Feb 2021 11:57:06 +0800
Subject: [PATCH 59/68] Update 11-Inner-Classes.md (#647)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Markdown格式修复
---
docs/book/11-Inner-Classes.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/book/11-Inner-Classes.md b/docs/book/11-Inner-Classes.md
index 66d3d5a1..91f363a7 100755
--- a/docs/book/11-Inner-Classes.md
+++ b/docs/book/11-Inner-Classes.md
@@ -698,7 +698,7 @@ public class TestBed {
f()
```
-这生成了一个独立的类 **TestBed$Tester**(要运行这个程序,执行 **java TestBed$Tester**,在 Unix/Linux 系统中需要转义 **$**)。你可以使用这个类测试,但是不必在发布的产品中包含它,可以在打包产品前删除 **TestBed$Tester.class**。
+这生成了一个独立的类 **TestBed$Tester**(要运行这个程序,执行 **java TestBed$Tester**,在 Unix/Linux 系统中需要转义 **$** )。你可以使用这个类测试,但是不必在发布的产品中包含它,可以在打包产品前删除 **TestBed$Tester.class**。
### 从多层嵌套类中访问外部类的成员
@@ -1434,7 +1434,7 @@ LocalInnerClass.class
虽然这种命名格式简单而直接,但它还是很健壮的,足以应对绝大多数情况[^1]。因为这是 Java 的标准命名方式,所以产生的文件自动都是平台无关的。(注意,为了保证你的内部类能起作用,Java 编译器会尽可能地转换它们。)
-[^1]: 另一方面,**$** 对Unix shell来说是一个元字符,所以当你列出.class文件时,有时会遇到麻烦。这对基于Unix的Sun公司来说有点奇怪。我的猜测是,他们没有考虑这个问题,而是认为你会很自然地关注源代码文件。
+[^1]: 另一方面, **$** 对Unix shell来说是一个元字符,所以当你列出.class文件时,有时会遇到麻烦。这对基于Unix的Sun公司来说有点奇怪。我的猜测是,他们没有考虑这个问题,而是认为你会很自然地关注源代码文件。
## 本章小结
From fc86061ccf7e39dd56a960c5cad3a5b29b4d90e7 Mon Sep 17 00:00:00 2001
From: iao113
Date: Sun, 7 Feb 2021 11:52:39 +0800
Subject: [PATCH 60/68] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=A8=8B=E5=BA=8F?=
=?UTF-8?q?=E8=BE=93=E5=87=BAtypo=20(#648)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* Update 12-Collections.md
程序输出typo
* Update 12-Collections.md
程序输出typo
---
docs/book/12-Collections.md | 150 ++++++++++--------------------------
1 file changed, 42 insertions(+), 108 deletions(-)
diff --git a/docs/book/12-Collections.md b/docs/book/12-Collections.md
index e34688fa..a8198174 100644
--- a/docs/book/12-Collections.md
+++ b/docs/book/12-Collections.md
@@ -57,10 +57,8 @@ public class ApplesAndOrangesWithoutGenerics {
/* Output:
___[ Error Output ]___
Exception in thread "main"
-java.lang.ClassCastException: Orange cannot be cast to
-Apple
- at ApplesAndOrangesWithoutGenerics.main(ApplesA
-ndOrangesWithoutGenerics.java:23)
+java.lang.ClassCastException: Orange cannot be cast to Apple
+ at ApplesAndOrangesWithoutGenerics.main(ApplesAndOrangesWithoutGenerics.java:23)
*/
```
@@ -178,7 +176,7 @@ public class SimpleCollection {
}
}
/* Output:
-0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
*/
```
@@ -553,14 +551,10 @@ public class CrossCollectionIteration {
}
}
/* Output:
-0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug
-7:Manx
-0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug
-7:Manx
-0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug
-7:Manx
-5:Cymric 2:Cymric 7:Manx 1:Manx 3:Mutt 6:Pug 4:Pug
-0:Rat
+0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx
+0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx
+0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx
+5:Cymric 2:Cymric 7:Manx 1:Manx 3:Mutt 6:Pug 4:Pug 0:Rat
*/
```
@@ -594,14 +588,10 @@ public class CrossCollectionIteration2 {
}
}
/* Output:
-0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug
-7:Manx
-0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug
-7:Manx
-0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug
-7:Manx
-5:Cymric 2:Cymric 7:Manx 1:Manx 3:Mutt 6:Pug 4:Pug
-0:Rat
+0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx
+0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx
+0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx
+5:Cymric 2:Cymric 7:Manx 1:Manx 3:Mutt 6:Pug 4:Pug 0:Rat
*/
```
@@ -640,12 +630,10 @@ public class ListIteration {
}
}
/* Output:
-Rat, 1, 0; Manx, 2, 1; Cymric, 3, 2; Mutt, 4, 3; Pug,
-5, 4; Cymric, 6, 5; Pug, 7, 6; Manx, 8, 7;
+Rat, 1, 0; Manx, 2, 1; Cymric, 3, 2; Mutt, 4, 3; Pug, 5, 4; Cymric, 6, 5; Pug, 7, 6; Manx, 8, 7;
7 6 5 4 3 2 1 0
[Rat, Manx, Cymric, Mutt, Pug, Cymric, Pug, Manx]
-[Rat, Manx, Cymric, Cymric, Rat, EgyptianMau, Hamster,
-EgyptianMau]
+[Rat, Manx, Cymric, Cymric, Rat, EgyptianMau, Hamster, EgyptianMau]
*/
```
@@ -854,8 +842,7 @@ public class SetOfInteger {
}
}
/* Output:
-[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
-16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]
+[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]
*/
```
@@ -952,8 +939,7 @@ set2 in set1: true
set1: [A, B, C, D, E, F, G, I, J, K, L, M]
set2 in set1: false
set2 removed from set1: [A, B, C, D, E, F, G, M]
-'X Y Z' added to set1: [A, B, C, D, E, F, G, M, X, Y,
-Z]
+'X Y Z' added to set1: [A, B, C, D, E, F, G, M, X, Y, Z]
*/
```
@@ -980,13 +966,7 @@ public class UniqueWords {
}
}
/* Output:
-[A, B, C, Collections, D, E, F, G, H, HashSet, I, J, K,
-L, M, N, Output, Set, SetOperations, String, System, X,
-Y, Z, add, addAll, added, args, class, collections,
-contains, containsAll, false, from, import, in, java,
-main, new, out, println, public, remove, removeAll,
-removed, set1, set2, split, static, to, true, util,
-void]
+[A, B, C, Collections, D, E, F, G, H, HashSet, I, J, K, L, M, N, Output, Set, SetOperations, String, System, X, Y, Z, add, addAll, added, args, class, collections, contains, containsAll, false, from, import, in, java, main, new, out, println, public, remove, removeAll, removed, set1, set2, split, static, to, true, util, void]
*/
```
@@ -1013,12 +993,7 @@ public class UniqueWordsAlphabetic {
}
}
/* Output:
-[A, add, addAll, added, args, B, C, class, collections,
-contains, containsAll, D, E, F, false, from, G, H,
-HashSet, I, import, in, J, java, K, L, M, main, N, new,
-out, Output, println, public, remove, removeAll,
-removed, Set, set1, set2, SetOperations, split, static,
-String, System, to, true, util, void, X, Y, Z]
+[A, add, addAll, added, args, B, C, class, collections, contains, containsAll, D, E, F, false, from, G, H, HashSet, I, import, in, J, java, K, L, M, main, N, new, out, Output, println, public, remove, removeAll, removed, Set, set1, set2, SetOperations, split, static, String, System, to, true, util, void, X, Y, Z]
*/
```
@@ -1051,9 +1026,7 @@ public class Statistics {
}
}
/* Output:
-{0=481, 1=502, 2=489, 3=508, 4=481, 5=503, 6=519,
-7=471, 8=468, 9=549, 10=513, 11=531, 12=521, 13=506,
-14=477, 15=497, 16=533, 17=509, 18=478, 19=464}
+{0=481, 1=502, 2=489, 3=508, 4=481, 5=503, 6=519, 7=471, 8=468, 9=549, 10=513, 11=531, 12=521, 13=506, 14=477, 15=497, 16=533, 17=509, 18=478, 19=464}
*/
```
@@ -1315,21 +1288,14 @@ public class InterfaceVsIterator {
}
}
/* Output:
-0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug
-7:Manx
-0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug
-7:Manx
-0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug
-7:Manx
-0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug
-7:Manx
-{Ralph=Rat, Eric=Manx, Robin=Cymric, Lacey=Mutt,
-Britney=Pug, Sam=Cymric, Spot=Pug, Fluffy=Manx}
+0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx
+0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx
+0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx
+0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx
+{Ralph=Rat, Eric=Manx, Robin=Cymric, Lacey=Mutt, Britney=Pug, Sam=Cymric, Spot=Pug, Fluffy=Manx}
[Ralph, Eric, Robin, Lacey, Britney, Sam, Spot, Fluffy]
-0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug
-7:Manx
-0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug
-7:Manx
+0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx
+0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx
*/
```
@@ -1372,10 +1338,8 @@ extends AbstractCollection {
}
}
/* Output:
-0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug
-7:Manx
-0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug
-7:Manx
+0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx
+0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx
*/
```
@@ -1417,8 +1381,7 @@ public class NonCollectionSequence extends PetSequence {
}
}
/* Output:
-0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug
-7:Manx
+0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx
*/
```
@@ -1729,64 +1692,35 @@ public class CollectionDifferences {
}
}
/* Output:
-Collection: [add, addAll, clear, contains, containsAll,
-equals, forEach, hashCode, isEmpty, iterator,
-parallelStream, remove, removeAll, removeIf, retainAll,
-size, spliterator, stream, toArray]
+Collection: [add, addAll, clear, contains, containsAll, equals, forEach, hashCode, isEmpty, iterator, parallelStream, remove, removeAll, removeIf, retainAll, size, spliterator, stream, toArray]
Interfaces in Collection: [Iterable]
Set extends Collection, adds: []
Interfaces in Set: [Collection]
HashSet extends Set, adds: []
Interfaces in HashSet: [Set, Cloneable, Serializable]
LinkedHashSet extends HashSet, adds: []
-Interfaces in LinkedHashSet: [Set, Cloneable,
-Serializable]
-TreeSet extends Set, adds: [headSet,
-descendingIterator, descendingSet, pollLast, subSet,
-floor, tailSet, ceiling, last, lower, comparator,
-pollFirst, first, higher]
-Interfaces in TreeSet: [NavigableSet, Cloneable,
-Serializable]
-List extends Collection, adds: [replaceAll, get,
-indexOf, subList, set, sort, lastIndexOf, listIterator]
+Interfaces in LinkedHashSet: [Set, Cloneable, Serializable]
+TreeSet extends Set, adds: [headSet, descendingIterator, descendingSet, pollLast, subSet, floor, tailSet, ceiling, last, lower, comparator, pollFirst, first, higher]
+Interfaces in TreeSet: [NavigableSet, Cloneable, Serializable]
+List extends Collection, adds: [replaceAll, get, indexOf, subList, set, sort, lastIndexOf, listIterator]
Interfaces in List: [Collection]
-ArrayList extends List, adds: [trimToSize,
-ensureCapacity]
-Interfaces in ArrayList: [List, RandomAccess,
-Cloneable, Serializable]
-LinkedList extends List, adds: [offerFirst, poll,
-getLast, offer, getFirst, removeFirst, element,
-removeLastOccurrence, peekFirst, peekLast, push,
-pollFirst, removeFirstOccurrence, descendingIterator,
-pollLast, removeLast, pop, addLast, peek, offerLast,
-addFirst]
-Interfaces in LinkedList: [List, Deque, Cloneable,
-Serializable]
-Queue extends Collection, adds: [poll, peek, offer,
-element]
+ArrayList extends List, adds: [trimToSize, ensureCapacity]
+Interfaces in ArrayList: [List, RandomAccess, Cloneable, Serializable]
+LinkedList extends List, adds: [offerFirst, poll, getLast, offer, getFirst, removeFirst, element, removeLastOccurrence, peekFirst, peekLast, push, pollFirst, removeFirstOccurrence, descendingIterator, pollLast, removeLast, pop, addLast, peek, offerLast, addFirst]
+Interfaces in LinkedList: [List, Deque, Cloneable, Serializable]
+Queue extends Collection, adds: [poll, peek, offer, element]
Interfaces in Queue: [Collection]
PriorityQueue extends Queue, adds: [comparator]
Interfaces in PriorityQueue: [Serializable]
-Map: [clear, compute, computeIfAbsent,
-computeIfPresent, containsKey, containsValue, entrySet,
-equals, forEach, get, getOrDefault, hashCode, isEmpty,
-keySet, merge, put, putAll, putIfAbsent, remove,
-replace, replaceAll, size, values]
+Map: [clear, compute, computeIfAbsent, computeIfPresent, containsKey, containsValue, entrySet, equals, forEach, get, getOrDefault, hashCode, isEmpty, keySet, merge, put, putAll, putIfAbsent, remove, replace, replaceAll, size, values]
HashMap extends Map, adds: []
Interfaces in HashMap: [Map, Cloneable, Serializable]
LinkedHashMap extends HashMap, adds: []
Interfaces in LinkedHashMap: [Map]
-SortedMap extends Map, adds: [lastKey, subMap,
-comparator, firstKey, headMap, tailMap]
+SortedMap extends Map, adds: [lastKey, subMap, comparator, firstKey, headMap, tailMap]
Interfaces in SortedMap: [Map]
-TreeMap extends Map, adds: [descendingKeySet,
-navigableKeySet, higherEntry, higherKey, floorKey,
-subMap, ceilingKey, pollLastEntry, firstKey, lowerKey,
-headMap, tailMap, lowerEntry, ceilingEntry,
-descendingMap, pollFirstEntry, lastKey, firstEntry,
-floorEntry, comparator, lastEntry]
-Interfaces in TreeMap: [NavigableMap, Cloneable,
-Serializable]
+TreeMap extends Map, adds: [descendingKeySet, navigableKeySet, higherEntry, higherKey, floorKey, subMap, ceilingKey, pollLastEntry, firstKey, lowerKey, headMap, tailMap, lowerEntry, ceilingEntry, descendingMap, pollFirstEntry, lastKey, firstEntry, floorEntry, comparator, lastEntry]
+Interfaces in TreeMap: [NavigableMap, Cloneable, Serializable]
*/
```
From 13038c489acdf8eda29e100f614028865cca4ee5 Mon Sep 17 00:00:00 2001
From: Guan
Date: Thu, 25 Feb 2021 12:30:00 +0800
Subject: [PATCH 61/68] =?UTF-8?q?fix:=20=E7=AC=AC=E4=B8=89=E7=AB=A0=20mark?=
=?UTF-8?q?down=20=E8=AF=AD=E6=B3=95=20(#649)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
docs/book/03-Objects-Everywhere.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/book/03-Objects-Everywhere.md b/docs/book/03-Objects-Everywhere.md
index 1c91e4b1..7c143f81 100644
--- a/docs/book/03-Objects-Everywhere.md
+++ b/docs/book/03-Objects-Everywhere.md
@@ -487,7 +487,7 @@ public class HelloDate {
选择 `java.lang`,你会看到该库中所有类的列表。由于 `java.lang` 隐式包含在每个 Java 代码文件中,因此这些类是自动可用的。`java.lang` 类库中没有 **Date** 类,所以我们必须导入其他的类库(即 Date 所在的类库)。如果你不清楚某个类所在的类库或者想查看类库中所有的类,那么可以在 Java 文档中选择 “Tree” 查看。
-现在,我们可以找到 Java 附带的每个类。使用浏览器的“查找”功能查找 **Date**,搜索结果中将会列出 **java.util.Date**,我们就知道了 **Date** 在 **util** 库中,所以必须导入 **java.util.*** 才能使用 **Date**。
+现在,我们可以找到 Java 附带的每个类。使用浏览器的“查找”功能查找 **Date**,搜索结果中将会列出 **java.util.Date**,我们就知道了 **Date** 在 **util** 库中,所以必须导入 **java.util.\*** 才能使用 **Date**。
如果你在文档中选择 **java.lang**,然后选择 **System**,你会看到 **System** 类中有几个字段,如果你选择了 **out**,你会发现它是一个静态的 **PrintStream** 对象。 所以,即使我们不使用 **new** 创建, **out** 对象就已经存在并可以使用。 **out** 对象可以执行的操作取决于它的类型: **PrintStream** ,其在文档中是一个超链接,如果单击该链接,我们将可以看到 **PrintStream** 对应的方法列表(更多详情,将在本书后面介绍)。 现在我们重点说的是 **println()** 这个方法。 它的作用是 “将信息输出到控制台,并以换行符结束”。既然如此,我们可以这样编码来输出信息到控制台。 代码示例:
From 1ef7ec48e492862300e667e24c245e9b3a5ccd98 Mon Sep 17 00:00:00 2001
From: Xin Wang
Date: Fri, 26 Feb 2021 15:46:06 +0800
Subject: [PATCH 62/68] Update 24-Concurrent-Programming.md (#651)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
更正翻译错误,"call" -> "调用了"
---
docs/book/24-Concurrent-Programming.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/book/24-Concurrent-Programming.md b/docs/book/24-Concurrent-Programming.md
index 67de4a97..0703d281 100755
--- a/docs/book/24-Concurrent-Programming.md
+++ b/docs/book/24-Concurrent-Programming.md
@@ -902,7 +902,7 @@ NapTask[8] pool-1-thread-1
NapTask[9] pool-1-thread-1
```
-一旦你 callexec.shutdown(),尝试提交新任务将抛出 RejectedExecutionException。
+一旦你调用了 exec.shutdown(),尝试提交新任务将抛出 RejectedExecutionException。
```java
// concurrent/MoreTasksAfterShutdown.java
From 3b0acf3d84d25774de79638a9c11ac904da3d6e9 Mon Sep 17 00:00:00 2001
From: LingCoder
Date: Fri, 26 Feb 2021 23:38:17 +0800
Subject: [PATCH 63/68] =?UTF-8?q?=E6=B8=85=E7=A9=BA=E9=A1=B9=E7=9B=AE?=
=?UTF-8?q?=E5=86=85=E5=AE=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
CONTRIBUTING.md | 45 -
README.md | 108 +-
SUMMARY.md | 448 --
book.json | 31 -
cover.jpg | Bin 117331 -> 0 bytes
cover_small.jpg | Bin 73325 -> 0 bytes
docs/.nojekyll | 0
docs/README.md | 43 -
docs/_coverpage.md | 25 -
docs/_style/prism-master/.editorconfig | 14 -
docs/_style/prism-master/.gitattributes | 4 -
docs/_style/prism-master/.gitignore | 4 -
docs/_style/prism-master/.npmignore | 27 -
docs/_style/prism-master/.travis.yml | 23 -
docs/_style/prism-master/CHANGELOG.md | 1334 -----
docs/_style/prism-master/CNAME | 1 -
docs/_style/prism-master/LICENSE | 21 -
docs/_style/prism-master/README.md | 30 -
docs/_style/prism-master/bower.json | 30 -
docs/_style/prism-master/code.js | 213 -
docs/_style/prism-master/components.js | 2 -
docs/_style/prism-master/components.json | 913 ---
docs/_style/prism-master/components/index.js | 82 -
.../prism-master/components/prism-abap.js | 48 -
.../prism-master/components/prism-abap.min.js | 1 -
.../components/prism-actionscript.js | 17 -
.../components/prism-actionscript.min.js | 1 -
.../prism-master/components/prism-ada.js | 19 -
.../prism-master/components/prism-ada.min.js | 1 -
.../components/prism-apacheconf.js | 47 -
.../components/prism-apacheconf.min.js | 1 -
.../prism-master/components/prism-apl.js | 32 -
.../prism-master/components/prism-apl.min.js | 1 -
.../components/prism-applescript.js | 20 -
.../components/prism-applescript.min.js | 1 -
.../prism-master/components/prism-arduino.js | 5 -
.../components/prism-arduino.min.js | 1 -
.../prism-master/components/prism-arff.js | 10 -
.../prism-master/components/prism-arff.min.js | 1 -
.../prism-master/components/prism-asciidoc.js | 271 -
.../components/prism-asciidoc.min.js | 1 -
.../prism-master/components/prism-asm6502.js | 28 -
.../components/prism-asm6502.min.js | 1 -
.../prism-master/components/prism-aspnet.js | 36 -
.../components/prism-aspnet.min.js | 1 -
.../components/prism-autohotkey.js | 27 -
.../components/prism-autohotkey.min.js | 1 -
.../prism-master/components/prism-autoit.js | 34 -
.../components/prism-autoit.min.js | 1 -
.../prism-master/components/prism-bash.js | 84 -
.../prism-master/components/prism-bash.min.js | 1 -
.../prism-master/components/prism-basic.js | 17 -
.../components/prism-basic.min.js | 1 -
.../prism-master/components/prism-batch.js | 99 -
.../components/prism-batch.min.js | 1 -
.../prism-master/components/prism-bison.js | 39 -
.../components/prism-bison.min.js | 1 -
.../components/prism-brainfuck.js | 20 -
.../components/prism-brainfuck.min.js | 1 -
.../prism-master/components/prism-bro.js | 48 -
.../prism-master/components/prism-bro.min.js | 1 -
.../_style/prism-master/components/prism-c.js | 33 -
.../prism-master/components/prism-c.min.js | 1 -
.../prism-master/components/prism-cil.js | 27 -
.../prism-master/components/prism-cil.min.js | 1 -
.../prism-master/components/prism-clike.js | 30 -
.../components/prism-clike.min.js | 1 -
.../prism-master/components/prism-clojure.js | 13 -
.../components/prism-clojure.min.js | 1 -
.../components/prism-coffeescript.js | 92 -
.../components/prism-coffeescript.min.js | 1 -
.../prism-master/components/prism-core.js | 548 --
.../prism-master/components/prism-core.min.js | 1 -
.../prism-master/components/prism-cpp.js | 20 -
.../prism-master/components/prism-cpp.min.js | 1 -
.../prism-master/components/prism-crystal.js | 51 -
.../components/prism-crystal.min.js | 1 -
.../prism-master/components/prism-csharp.js | 81 -
.../components/prism-csharp.min.js | 1 -
.../prism-master/components/prism-csp.js | 25 -
.../prism-master/components/prism-csp.min.js | 1 -
.../components/prism-css-extras.js | 31 -
.../components/prism-css-extras.min.js | 1 -
.../prism-master/components/prism-css.js | 52 -
.../prism-master/components/prism-css.min.js | 1 -
.../_style/prism-master/components/prism-d.js | 64 -
.../prism-master/components/prism-d.min.js | 1 -
.../prism-master/components/prism-dart.js | 24 -
.../prism-master/components/prism-dart.min.js | 1 -
.../prism-master/components/prism-diff.js | 20 -
.../prism-master/components/prism-diff.min.js | 1 -
.../prism-master/components/prism-django.js | 41 -
.../components/prism-django.min.js | 1 -
.../prism-master/components/prism-docker.js | 11 -
.../components/prism-docker.min.js | 1 -
.../prism-master/components/prism-eiffel.js | 37 -
.../components/prism-eiffel.min.js | 1 -
.../prism-master/components/prism-elixir.js | 93 -
.../components/prism-elixir.min.js | 1 -
.../prism-master/components/prism-elm.js | 44 -
.../prism-master/components/prism-elm.min.js | 1 -
.../prism-master/components/prism-erb.js | 20 -
.../prism-master/components/prism-erb.min.js | 1 -
.../prism-master/components/prism-erlang.js | 44 -
.../components/prism-erlang.min.js | 1 -
.../prism-master/components/prism-flow.js | 35 -
.../prism-master/components/prism-flow.min.js | 1 -
.../prism-master/components/prism-fortran.js | 40 -
.../components/prism-fortran.min.js | 1 -
.../prism-master/components/prism-fsharp.js | 67 -
.../components/prism-fsharp.min.js | 1 -
.../prism-master/components/prism-gcode.js | 15 -
.../components/prism-gcode.min.js | 1 -
.../prism-master/components/prism-gedcom.js | 28 -
.../components/prism-gedcom.min.js | 1 -
.../prism-master/components/prism-gherkin.js | 79 -
.../components/prism-gherkin.min.js | 1 -
.../prism-master/components/prism-git.js | 68 -
.../prism-master/components/prism-git.min.js | 1 -
.../prism-master/components/prism-glsl.js | 16 -
.../prism-master/components/prism-glsl.min.js | 1 -
.../prism-master/components/prism-gml.js | 7 -
.../prism-master/components/prism-gml.min.js | 1 -
.../prism-master/components/prism-go.js | 12 -
.../prism-master/components/prism-go.min.js | 1 -
.../prism-master/components/prism-graphql.js | 24 -
.../components/prism-graphql.min.js | 1 -
.../prism-master/components/prism-groovy.js | 65 -
.../components/prism-groovy.min.js | 1 -
.../prism-master/components/prism-haml.js | 154 -
.../prism-master/components/prism-haml.min.js | 1 -
.../components/prism-handlebars.js | 37 -
.../components/prism-handlebars.min.js | 1 -
.../prism-master/components/prism-haskell.js | 36 -
.../components/prism-haskell.min.js | 1 -
.../prism-master/components/prism-haxe.js | 45 -
.../prism-master/components/prism-haxe.min.js | 1 -
.../prism-master/components/prism-hpkp.js | 20 -
.../prism-master/components/prism-hpkp.min.js | 1 -
.../prism-master/components/prism-hsts.js | 20 -
.../prism-master/components/prism-hsts.min.js | 1 -
.../prism-master/components/prism-http.js | 79 -
.../prism-master/components/prism-http.min.js | 1 -
.../components/prism-ichigojam.js | 15 -
.../components/prism-ichigojam.min.js | 1 -
.../prism-master/components/prism-icon.js | 20 -
.../prism-master/components/prism-icon.min.js | 1 -
.../prism-master/components/prism-inform7.js | 61 -
.../components/prism-inform7.min.js | 1 -
.../prism-master/components/prism-ini.js | 11 -
.../prism-master/components/prism-ini.min.js | 1 -
.../prism-master/components/prism-io.js | 31 -
.../prism-master/components/prism-io.min.js | 1 -
.../_style/prism-master/components/prism-j.js | 25 -
.../prism-master/components/prism-j.min.js | 1 -
.../prism-master/components/prism-java.js | 54 -
.../prism-master/components/prism-java.min.js | 1 -
.../components/prism-javascript.js | 91 -
.../components/prism-javascript.min.js | 1 -
.../components/prism-javastacktrace.js | 93 -
.../components/prism-javastacktrace.min.js | 1 -
.../prism-master/components/prism-jolie.js | 55 -
.../components/prism-jolie.min.js | 1 -
.../prism-master/components/prism-json.js | 18 -
.../prism-master/components/prism-json.min.js | 1 -
.../prism-master/components/prism-jsx.js | 126 -
.../prism-master/components/prism-jsx.min.js | 1 -
.../prism-master/components/prism-julia.js | 12 -
.../components/prism-julia.min.js | 1 -
.../prism-master/components/prism-keyman.js | 14 -
.../components/prism-keyman.min.js | 1 -
.../prism-master/components/prism-kotlin.js | 62 -
.../components/prism-kotlin.min.js | 1 -
.../prism-master/components/prism-latex.js | 61 -
.../components/prism-latex.min.js | 1 -
.../prism-master/components/prism-less.js | 54 -
.../prism-master/components/prism-less.min.js | 1 -
.../prism-master/components/prism-liquid.js | 12 -
.../components/prism-liquid.min.js | 1 -
.../prism-master/components/prism-lisp.js | 197 -
.../prism-master/components/prism-lisp.min.js | 1 -
.../components/prism-livescript.js | 119 -
.../components/prism-livescript.min.js | 1 -
.../prism-master/components/prism-lolcode.js | 55 -
.../components/prism-lolcode.min.js | 1 -
.../prism-master/components/prism-lua.js | 20 -
.../prism-master/components/prism-lua.min.js | 1 -
.../prism-master/components/prism-makefile.js | 34 -
.../components/prism-makefile.min.js | 1 -
.../prism-master/components/prism-markdown.js | 229 -
.../components/prism-markdown.min.js | 1 -
.../components/prism-markup-templating.js | 89 -
.../components/prism-markup-templating.min.js | 1 -
.../prism-master/components/prism-markup.js | 56 -
.../components/prism-markup.min.js | 1 -
.../prism-master/components/prism-matlab.js | 16 -
.../components/prism-matlab.min.js | 1 -
.../prism-master/components/prism-mel.js | 43 -
.../prism-master/components/prism-mel.min.js | 1 -
.../prism-master/components/prism-mizar.js | 12 -
.../components/prism-mizar.min.js | 1 -
.../prism-master/components/prism-monkey.js | 31 -
.../components/prism-monkey.min.js | 1 -
.../prism-master/components/prism-n4js.js | 14 -
.../prism-master/components/prism-n4js.min.js | 1 -
.../prism-master/components/prism-nasm.js | 24 -
.../prism-master/components/prism-nasm.min.js | 1 -
.../prism-master/components/prism-nginx.js | 11 -
.../components/prism-nginx.min.js | 1 -
.../prism-master/components/prism-nim.js | 33 -
.../prism-master/components/prism-nim.min.js | 1 -
.../prism-master/components/prism-nix.js | 40 -
.../prism-master/components/prism-nix.min.js | 1 -
.../prism-master/components/prism-nsis.js | 29 -
.../prism-master/components/prism-nsis.min.js | 1 -
.../components/prism-objectivec.js | 5 -
.../components/prism-objectivec.min.js | 1 -
.../prism-master/components/prism-ocaml.js | 27 -
.../components/prism-ocaml.min.js | 1 -
.../prism-master/components/prism-opencl.js | 49 -
.../components/prism-opencl.min.js | 1 -
.../prism-master/components/prism-oz.js | 25 -
.../prism-master/components/prism-oz.min.js | 1 -
.../prism-master/components/prism-parigp.js | 30 -
.../components/prism-parigp.min.js | 1 -
.../prism-master/components/prism-parser.js | 67 -
.../components/prism-parser.min.js | 1 -
.../prism-master/components/prism-pascal.js | 55 -
.../components/prism-pascal.min.js | 1 -
.../prism-master/components/prism-perl.js | 191 -
.../prism-master/components/prism-perl.min.js | 1 -
.../components/prism-php-extras.js | 11 -
.../components/prism-php-extras.min.js | 1 -
.../prism-master/components/prism-php.js | 122 -
.../prism-master/components/prism-php.min.js | 1 -
.../prism-master/components/prism-plsql.js | 20 -
.../components/prism-plsql.min.js | 1 -
.../components/prism-powershell.js | 55 -
.../components/prism-powershell.min.js | 1 -
.../components/prism-processing.js | 18 -
.../components/prism-processing.min.js | 1 -
.../prism-master/components/prism-prolog.js | 20 -
.../components/prism-prolog.min.js | 1 -
.../components/prism-properties.js | 9 -
.../components/prism-properties.min.js | 1 -
.../prism-master/components/prism-protobuf.js | 8 -
.../components/prism-protobuf.min.js | 1 -
.../prism-master/components/prism-pug.js | 198 -
.../prism-master/components/prism-pug.min.js | 1 -
.../prism-master/components/prism-puppet.js | 136 -
.../components/prism-puppet.min.js | 1 -
.../prism-master/components/prism-pure.js | 81 -
.../prism-master/components/prism-pure.min.js | 1 -
.../prism-master/components/prism-python.js | 64 -
.../components/prism-python.min.js | 1 -
.../_style/prism-master/components/prism-q.js | 51 -
.../prism-master/components/prism-q.min.js | 1 -
.../prism-master/components/prism-qore.js | 20 -
.../prism-master/components/prism-qore.min.js | 1 -
.../_style/prism-master/components/prism-r.js | 22 -
.../prism-master/components/prism-r.min.js | 1 -
.../prism-master/components/prism-reason.js | 32 -
.../components/prism-reason.min.js | 1 -
.../prism-master/components/prism-renpy.js | 29 -
.../components/prism-renpy.min.js | 1 -
.../prism-master/components/prism-rest.js | 205 -
.../prism-master/components/prism-rest.min.js | 1 -
.../prism-master/components/prism-rip.js | 32 -
.../prism-master/components/prism-rip.min.js | 1 -
.../prism-master/components/prism-roboconf.js | 27 -
.../components/prism-roboconf.min.js | 1 -
.../prism-master/components/prism-ruby.js | 143 -
.../prism-master/components/prism-ruby.min.js | 1 -
.../prism-master/components/prism-rust.js | 68 -
.../prism-master/components/prism-rust.min.js | 1 -
.../prism-master/components/prism-sas.js | 34 -
.../prism-master/components/prism-sas.min.js | 1 -
.../prism-master/components/prism-sass.js | 72 -
.../prism-master/components/prism-sass.min.js | 1 -
.../prism-master/components/prism-scala.js | 18 -
.../components/prism-scala.min.js | 1 -
.../prism-master/components/prism-scheme.js | 33 -
.../components/prism-scheme.min.js | 1 -
.../prism-master/components/prism-scss.js | 74 -
.../prism-master/components/prism-scss.min.js | 1 -
.../components/prism-smalltalk.js | 31 -
.../components/prism-smalltalk.min.js | 1 -
.../prism-master/components/prism-smarty.js | 96 -
.../components/prism-smarty.min.js | 1 -
.../prism-master/components/prism-soy.js | 96 -
.../prism-master/components/prism-soy.min.js | 1 -
.../prism-master/components/prism-sql.js | 24 -
.../prism-master/components/prism-sql.min.js | 1 -
.../prism-master/components/prism-stylus.js | 111 -
.../components/prism-stylus.min.js | 1 -
.../prism-master/components/prism-swift.js | 25 -
.../components/prism-swift.min.js | 1 -
.../prism-master/components/prism-tap.js | 20 -
.../prism-master/components/prism-tap.min.js | 1 -
.../prism-master/components/prism-tcl.js | 46 -
.../prism-master/components/prism-tcl.min.js | 1 -
.../prism-master/components/prism-textile.js | 257 -
.../components/prism-textile.min.js | 1 -
.../prism-master/components/prism-toml.js | 43 -
.../prism-master/components/prism-toml.min.js | 1 -
.../prism-master/components/prism-tsx.js | 2 -
.../prism-master/components/prism-tsx.min.js | 1 -
.../prism-master/components/prism-tt2.js | 56 -
.../prism-master/components/prism-tt2.min.js | 1 -
.../prism-master/components/prism-twig.js | 46 -
.../prism-master/components/prism-twig.min.js | 1 -
.../components/prism-typescript.js | 7 -
.../components/prism-typescript.min.js | 1 -
.../prism-master/components/prism-vala.js | 74 -
.../prism-master/components/prism-vala.min.js | 1 -
.../prism-master/components/prism-vbnet.js | 15 -
.../components/prism-vbnet.min.js | 1 -
.../prism-master/components/prism-velocity.js | 72 -
.../components/prism-velocity.min.js | 1 -
.../prism-master/components/prism-verilog.js | 20 -
.../components/prism-verilog.min.js | 1 -
.../prism-master/components/prism-vhdl.js | 23 -
.../prism-master/components/prism-vhdl.min.js | 1 -
.../prism-master/components/prism-vim.js | 10 -
.../prism-master/components/prism-vim.min.js | 1 -
.../components/prism-visual-basic.js | 34 -
.../components/prism-visual-basic.min.js | 1 -
.../prism-master/components/prism-wasm.js | 31 -
.../prism-master/components/prism-wasm.min.js | 1 -
.../prism-master/components/prism-wiki.js | 81 -
.../prism-master/components/prism-wiki.min.js | 1 -
.../prism-master/components/prism-xeora.js | 114 -
.../components/prism-xeora.min.js | 1 -
.../prism-master/components/prism-xojo.js | 20 -
.../prism-master/components/prism-xojo.min.js | 1 -
.../prism-master/components/prism-xquery.js | 164 -
.../components/prism-xquery.min.js | 1 -
.../prism-master/components/prism-yaml.js | 47 -
.../prism-master/components/prism-yaml.min.js | 1 -
docs/_style/prism-master/composer.json | 20 -
docs/_style/prism-master/download.html | 193 -
docs/_style/prism-master/download.js | 598 --
docs/_style/prism-master/examples.html | 110 -
docs/_style/prism-master/examples.js | 217 -
.../prism-master/examples/prism-abap.html | 65 -
.../examples/prism-actionscript.html | 133 -
.../prism-master/examples/prism-ada.html | 35 -
.../examples/prism-apacheconf.html | 54 -
.../prism-master/examples/prism-apl.html | 26 -
.../examples/prism-applescript.html | 41 -
.../prism-master/examples/prism-arduino.html | 63 -
.../prism-master/examples/prism-arff.html | 46 -
.../prism-master/examples/prism-asciidoc.html | 104 -
.../prism-master/examples/prism-asm6502.html | 39 -
.../prism-master/examples/prism-aspnet.html | 36 -
.../examples/prism-autohotkey.html | 68 -
.../prism-master/examples/prism-autoit.html | 52 -
.../prism-master/examples/prism-bash.html | 49 -
.../prism-master/examples/prism-basic.html | 69 -
.../prism-master/examples/prism-batch.html | 17 -
.../prism-master/examples/prism-bison.html | 104 -
.../examples/prism-brainfuck.html | 37 -
.../prism-master/examples/prism-bro.html | 645 --
.../_style/prism-master/examples/prism-c.html | 22 -
.../prism-master/examples/prism-clike.html | 28 -
.../prism-master/examples/prism-clojure.html | 386 --
.../examples/prism-coffeescript.html | 61 -
.../prism-master/examples/prism-cpp.html | 61 -
.../prism-master/examples/prism-crystal.html | 16 -
.../prism-master/examples/prism-csharp.html | 60 -
.../prism-master/examples/prism-csp.html | 13 -
.../prism-master/examples/prism-css.html | 34 -
.../_style/prism-master/examples/prism-d.html | 267 -
.../prism-master/examples/prism-dart.html | 59 -
.../prism-master/examples/prism-diff.html | 33 -
.../prism-master/examples/prism-django.html | 31 -
.../prism-master/examples/prism-docker.html | 49 -
.../prism-master/examples/prism-eiffel.html | 72 -
.../prism-master/examples/prism-elixir.html | 462 --
.../prism-master/examples/prism-elm.html | 91 -
.../prism-master/examples/prism-erb.html | 22 -
.../prism-master/examples/prism-erlang.html | 47 -
.../prism-master/examples/prism-flow.html | 18 -
.../prism-master/examples/prism-fortran.html | 71 -
.../prism-master/examples/prism-fsharp.html | 89 -
.../prism-master/examples/prism-gcode.html | 22 -
.../prism-master/examples/prism-gedcom.html | 50 -
.../prism-master/examples/prism-gherkin.html | 74 -
.../prism-master/examples/prism-git.html | 39 -
.../prism-master/examples/prism-glsl.html | 65 -
.../prism-master/examples/prism-gml.html | 29 -
.../prism-master/examples/prism-go.html | 68 -
.../prism-master/examples/prism-graphql.html | 31 -
.../prism-master/examples/prism-groovy.html | 93 -
.../prism-master/examples/prism-haml.html | 79 -
.../examples/prism-handlebars.html | 41 -
.../prism-master/examples/prism-haskell.html | 80 -
.../prism-master/examples/prism-haxe.html | 37 -
.../prism-master/examples/prism-hpkp.html | 11 -
.../prism-master/examples/prism-hsts.html | 8 -
.../prism-master/examples/prism-http.html | 33 -
.../examples/prism-ichigojam.html | 29 -
.../prism-master/examples/prism-icon.html | 172 -
.../prism-master/examples/prism-inform7.html | 171 -
.../prism-master/examples/prism-ini.html | 10 -
.../prism-master/examples/prism-io.html | 31 -
.../_style/prism-master/examples/prism-j.html | 59 -
.../prism-master/examples/prism-java.html | 65 -
.../examples/prism-javascript.html | 77 -
.../examples/prism-javastacktrace.html | 63 -
.../prism-master/examples/prism-jolie.html | 162 -
.../prism-master/examples/prism-jsx.html | 18 -
.../prism-master/examples/prism-julia.html | 29 -
.../prism-master/examples/prism-keyman.html | 107 -
.../prism-master/examples/prism-kotlin.html | 134 -
.../prism-master/examples/prism-latex.html | 12 -
.../prism-master/examples/prism-less.html | 70 -
.../prism-master/examples/prism-liquid.html | 75 -
.../prism-master/examples/prism-lisp.html | 46 -
.../examples/prism-livescript.html | 84 -
.../prism-master/examples/prism-lolcode.html | 62 -
.../prism-master/examples/prism-lua.html | 89 -
.../prism-master/examples/prism-makefile.html | 263 -
.../prism-master/examples/prism-markdown.html | 86 -
.../prism-master/examples/prism-markup.html | 77 -
.../prism-master/examples/prism-matlab.html | 52 -
.../prism-master/examples/prism-mel.html | 137 -
.../prism-master/examples/prism-mizar.html | 45 -
.../prism-master/examples/prism-monkey.html | 74 -
.../prism-master/examples/prism-n4js.html | 114 -
.../prism-master/examples/prism-nasm.html | 74 -
.../prism-master/examples/prism-nginx.html | 25 -
.../prism-master/examples/prism-nim.html | 222 -
.../prism-master/examples/prism-nix.html | 46 -
.../prism-master/examples/prism-nsis.html | 18 -
.../examples/prism-objectivec.html | 44 -
.../prism-master/examples/prism-ocaml.html | 59 -
.../prism-master/examples/prism-opencl.html | 83 -
.../prism-master/examples/prism-oz.html | 89 -
.../prism-master/examples/prism-parigp.html | 20 -
.../prism-master/examples/prism-parser.html | 88 -
.../prism-master/examples/prism-pascal.html | 65 -
.../prism-master/examples/prism-perl.html | 71 -
.../prism-master/examples/prism-php.html | 67 -
.../prism-master/examples/prism-plsql.html | 40 -
.../examples/prism-powershell.html | 19 -
.../examples/prism-processing.html | 173 -
.../prism-master/examples/prism-prolog.html | 44 -
.../examples/prism-properties.html | 9 -
.../prism-master/examples/prism-pug.html | 85 -
.../prism-master/examples/prism-puppet.html | 152 -
.../prism-master/examples/prism-pure.html | 115 -
.../prism-master/examples/prism-python.html | 61 -
.../_style/prism-master/examples/prism-q.html | 112 -
.../prism-master/examples/prism-qore.html | 962 ---
.../_style/prism-master/examples/prism-r.html | 38 -
.../prism-master/examples/prism-reason.html | 35 -
.../prism-master/examples/prism-renpy.html | 123 -
.../prism-master/examples/prism-rest.html | 329 --
.../prism-master/examples/prism-rip.html | 12 -
.../prism-master/examples/prism-roboconf.html | 49 -
.../prism-master/examples/prism-ruby.html | 30 -
.../prism-master/examples/prism-rust.html | 68 -
.../prism-master/examples/prism-sas.html | 158 -
.../prism-master/examples/prism-sass.html | 47 -
.../prism-master/examples/prism-scala.html | 100 -
.../prism-master/examples/prism-scheme.html | 35 -
.../prism-master/examples/prism-scss.html | 31 -
.../examples/prism-smalltalk.html | 92 -
.../prism-master/examples/prism-smarty.html | 81 -
.../prism-master/examples/prism-soy.html | 36 -
.../prism-master/examples/prism-sql.html | 34 -
.../prism-master/examples/prism-stylus.html | 72 -
.../prism-master/examples/prism-swift.html | 80 -
.../prism-master/examples/prism-tcl.html | 26 -
.../prism-master/examples/prism-textile.html | 178 -
.../prism-master/examples/prism-tsx.html | 31 -
.../prism-master/examples/prism-tt2.html | 61 -
.../prism-master/examples/prism-twig.html | 35 -
.../examples/prism-typescript.html | 28 -
.../prism-master/examples/prism-vala.html | 33 -
.../prism-master/examples/prism-vbnet.html | 16 -
.../prism-master/examples/prism-velocity.html | 47 -
.../prism-master/examples/prism-verilog.html | 103 -
.../prism-master/examples/prism-vhdl.html | 92 -
.../prism-master/examples/prism-vim.html | 25 -
.../examples/prism-visual-basic.html | 36 -
.../prism-master/examples/prism-wasm.html | 43 -
.../prism-master/examples/prism-wiki.html | 165 -
.../prism-master/examples/prism-xeora.html | 111 -
.../prism-master/examples/prism-xojo.html | 63 -
.../prism-master/examples/prism-xquery.html | 47 -
.../prism-master/examples/prism-yaml.html | 107 -
docs/_style/prism-master/extending.html | 247 -
docs/_style/prism-master/faq.html | 182 -
docs/_style/prism-master/favicon.png | Bin 209 -> 0 bytes
docs/_style/prism-master/gulpfile.js | 143 -
docs/_style/prism-master/img/logo-ala.png | Bin 1745 -> 0 bytes
.../prism-master/img/logo-css-tricks.png | Bin 1735 -> 0 bytes
docs/_style/prism-master/img/logo-drupal.png | Bin 2371 -> 0 bytes
docs/_style/prism-master/img/logo-mdn.png | Bin 6677 -> 0 bytes
docs/_style/prism-master/img/logo-react.png | Bin 4705 -> 0 bytes
.../prism-master/img/logo-sitepoint.png | Bin 2703 -> 0 bytes
.../_style/prism-master/img/logo-smashing.png | Bin 14160 -> 0 bytes
docs/_style/prism-master/img/logo-stripe.png | Bin 3377 -> 0 bytes
docs/_style/prism-master/img/spectrum.png | Bin 359393 -> 0 bytes
docs/_style/prism-master/index.html | 321 -
docs/_style/prism-master/logo.svg | 22 -
docs/_style/prism-master/package.json | 47 -
.../plugins/autolinker/index.html | 70 -
.../plugins/autolinker/prism-autolinker.css | 3 -
.../plugins/autolinker/prism-autolinker.js | 81 -
.../autolinker/prism-autolinker.min.js | 1 -
.../plugins/autoloader/index.html | 204 -
.../plugins/autoloader/prism-autoloader.js | 209 -
.../autoloader/prism-autoloader.min.js | 1 -
.../plugins/command-line/index.html | 111 -
.../command-line/prism-command-line.css | 33 -
.../command-line/prism-command-line.js | 139 -
.../command-line/prism-command-line.min.js | 1 -
.../plugins/copy-to-clipboard/index.html | 48 -
.../prism-copy-to-clipboard.js | 75 -
.../prism-copy-to-clipboard.min.js | 1 -
.../plugins/custom-class/index.html | 133 -
.../custom-class/prism-custom-class.js | 31 -
.../custom-class/prism-custom-class.min.js | 1 -
.../plugins/data-uri-highlight/index.html | 60 -
.../prism-data-uri-highlight.js | 98 -
.../prism-data-uri-highlight.min.js | 1 -
.../plugins/file-highlight/index.html | 75 -
.../file-highlight/prism-file-highlight.js | 105 -
.../prism-file-highlight.min.js | 1 -
.../plugins/highlight-keywords/index.html | 51 -
.../prism-highlight-keywords.js | 17 -
.../prism-highlight-keywords.min.js | 1 -
docs/_style/prism-master/plugins/index.html | 42 -
.../plugins/jsonp-highlight/index.html | 174 -
.../jsonp-highlight/prism-jsonp-highlight.js | 151 -
.../prism-jsonp-highlight.min.js | 1 -
.../plugins/keep-markup/index.html | 80 -
.../plugins/keep-markup/prism-keep-markup.js | 99 -
.../keep-markup/prism-keep-markup.min.js | 1 -
.../plugins/line-highlight/index.html | 88 -
.../line-highlight/prism-line-highlight.css | 49 -
.../line-highlight/prism-line-highlight.js | 181 -
.../prism-line-highlight.min.js | 1 -
.../plugins/line-numbers/index.html | 69 -
.../line-numbers/prism-line-numbers.css | 41 -
.../line-numbers/prism-line-numbers.js | 159 -
.../line-numbers/prism-line-numbers.min.js | 1 -
.../plugins/normalize-whitespace/demo.html | 33 -
.../plugins/normalize-whitespace/index.html | 180 -
.../prism-normalize-whitespace.js | 190 -
.../prism-normalize-whitespace.min.js | 1 -
.../plugins/previewers/index.html | 233 -
.../plugins/previewers/prism-previewers.css | 242 -
.../plugins/previewers/prism-previewers.js | 708 ---
.../previewers/prism-previewers.min.js | 1 -
.../remove-initial-line-feed/index.html | 59 -
.../prism-remove-initial-line-feed.js | 21 -
.../prism-remove-initial-line-feed.min.js | 1 -
.../plugins/show-invisibles/index.html | 46 -
.../show-invisibles/prism-show-invisibles.css | 34 -
.../show-invisibles/prism-show-invisibles.js | 21 -
.../prism-show-invisibles.min.js | 1 -
.../plugins/show-language/index.html | 54 -
.../show-language/prism-show-language.js | 31 -
.../show-language/prism-show-language.min.js | 1 -
.../prism-master/plugins/toolbar/index.html | 134 -
.../plugins/toolbar/prism-toolbar.css | 58 -
.../plugins/toolbar/prism-toolbar.js | 137 -
.../plugins/toolbar/prism-toolbar.min.js | 1 -
.../plugins/unescaped-markup/index.html | 195 -
.../prism-unescaped-markup.css | 10 -
.../prism-unescaped-markup.js | 44 -
.../prism-unescaped-markup.min.js | 1 -
.../prism-master/plugins/wpd/index.html | 68 -
.../prism-master/plugins/wpd/prism-wpd.css | 11 -
.../prism-master/plugins/wpd/prism-wpd.js | 169 -
.../prism-master/plugins/wpd/prism-wpd.min.js | 1 -
docs/_style/prism-master/prefixfree.min.js | 5 -
docs/_style/prism-master/prism.js | 917 ---
docs/_style/prism-master/style.css | 407 --
.../_style/prism-master/templates/footer.html | 15 -
.../templates/header-download.html | 2 -
.../prism-master/templates/header-main.html | 12 -
.../templates/header-plugins.html | 8 -
docs/_style/prism-master/test-suite.html | 167 -
docs/_style/prism-master/test.html | 203 -
.../prism-master/tests/helper/prism-loader.js | 131 -
.../prism-master/tests/helper/test-case.js | 196 -
.../tests/helper/test-discovery.js | 115 -
.../tests/helper/token-stream-transformer.js | 32 -
.../tests/languages/abap/comment_feature.test | 13 -
.../languages/abap/eol-comment_feature.test | 13 -
.../tests/languages/abap/keyword_feature.test | 1801 ------
.../tests/languages/abap/number_feature.test | 15 -
.../languages/abap/operator_feature.test | 38 -
.../abap/string-template_feature.test | 17 -
.../tests/languages/abap/string_feature.test | 21 -
.../actionscript/keyword_feature.test | 71 -
.../actionscript/operator_feature.test | 29 -
.../languages/ada/attr-name_feature.test | 13 -
.../tests/languages/ada/boolean_feature.test | 13 -
.../tests/languages/ada/char_feature.test | 13 -
.../tests/languages/ada/comment_feature.test | 13 -
.../tests/languages/ada/keyword_feature.test | 153 -
.../tests/languages/ada/number_feature.test | 21 -
.../tests/languages/ada/operator_feature.test | 23 -
.../tests/languages/ada/string_feature.test | 13 -
.../tests/languages/ada/variable_feature.test | 13 -
.../languages/apacheconf/comment_feature.test | 15 -
.../apacheconf/directive-block_feature.test | 469 --
.../apacheconf/directive-flags_feature.test | 13 -
.../apacheconf/directive-inline_feature.test | 1163 ----
.../languages/apacheconf/regex_feature.test | 15 -
.../languages/apacheconf/string_feature.test | 24 -
.../apacheconf/variable_feature.test | 15 -
.../languages/apl/assignment_feature.test | 13 -
.../tests/languages/apl/comment_feature.test | 15 -
.../tests/languages/apl/constant_feature.test | 19 -
.../tests/languages/apl/dfn_feature.test | 23 -
.../apl/dyadic-operator_feature.test | 15 -
.../tests/languages/apl/function_feature.test | 43 -
.../apl/monadic-operator_feature.test | 15 -
.../tests/languages/apl/number_feature.test | 27 -
.../languages/apl/statement_feature.test | 13 -
.../tests/languages/apl/string_feature.test | 15 -
.../apl/system-function_feature.test | 17 -
.../languages/applescript/class_feature.test | 39 -
.../applescript/comment_feature.test | 21 -
.../applescript/keyword_feature.test | 59 -
.../languages/applescript/number_feature.test | 17 -
.../applescript/operator_feature.test | 48 -
.../languages/applescript/string_feature.test | 13 -
.../tests/languages/arff/comment_feature.test | 15 -
.../tests/languages/arff/keyword_feature.test | 17 -
.../tests/languages/arff/number_feature.test | 13 -
.../tests/languages/arff/string_feature.test | 13 -
.../asciidoc/admonition_feature.test | 19 -
.../asciidoc/attribute-entry_feature.test | 58 -
.../asciidoc/attributes_feature.test | 403 --
.../languages/asciidoc/callout_feature.test | 34 -
.../asciidoc/comment-block_feature.test | 19 -
.../languages/asciidoc/comment_feature.test | 41 -
.../languages/asciidoc/entity_feature.js | 4 -
.../languages/asciidoc/entity_feature.test | 48 -
.../tests/languages/asciidoc/hr_feature.test | 14 -
.../asciidoc/indented-block_feature.test | 28 -
.../languages/asciidoc/inline_feature.test | 521 --
.../asciidoc/line-continuation_feature.test | 18 -
.../asciidoc/list-label_feature.test | 73 -
.../asciidoc/list-punctuation_feature.test | 77 -
.../asciidoc/literal-block_feature.test | 46 -
.../languages/asciidoc/macro_feature.test | 250 -
.../asciidoc/other-block_feature.test | 45 -
.../asciidoc/page-break_feature.test | 14 -
.../asciidoc/passthrough-block_feature.test | 29 -
.../asciidoc/replacement_feature.test | 48 -
.../languages/asciidoc/table_feature.test | 61 -
.../languages/asciidoc/title_feature.test | 80 -
.../languages/asm6502/comment_feature.test | 13 -
.../languages/asm6502/directive_feature.test | 12 -
.../languages/asm6502/number_feature.test | 18 -
.../languages/asm6502/opcode_feature.test | 17 -
.../languages/asm6502/register_feature.test | 17 -
.../languages/asm6502/string_feature.test | 12 -
.../languages/aspnet/comment_feature.test | 16 -
.../aspnet/page-directive_feature.test | 92 -
.../languages/autohotkey/boolean_feature.test | 13 -
.../languages/autohotkey/builtin_feature.test | 147 -
.../languages/autohotkey/comment_feature.test | 13 -
.../autohotkey/constant_feature.test | 275 -
.../autohotkey/function_feature.test | 15 -
.../autohotkey/important_feature.test | 67 -
.../languages/autohotkey/keyword_feature.test | 537 --
.../languages/autohotkey/number_feature.test | 21 -
.../autohotkey/operator_feature.test | 33 -
.../autohotkey/selector_feature.test | 381 --
.../languages/autohotkey/string_feature.test | 15 -
.../languages/autohotkey/symbol_feature.test | 347 --
.../languages/autohotkey/tag_feature.test | 15 -
.../autohotkey/variable_feature.test | 13 -
.../languages/autoit/boolean_feature.test | 13 -
.../languages/autoit/comment_feature.test | 33 -
.../languages/autoit/directive_feature.test | 13 -
.../languages/autoit/function_feature.test | 15 -
.../languages/autoit/keyword_feature.test | 83 -
.../languages/autoit/number_feature.test | 21 -
.../languages/autoit/operator_feature.test | 23 -
.../languages/autoit/string_feature.test | 37 -
.../tests/languages/autoit/url_feature.test | 15 -
.../languages/autoit/variable_feature.test | 19 -
.../bash/arithmetic_environment_feature.test | 53 -
.../bash/command_substitution_feature.test | 45 -
.../tests/languages/bash/comment_feature.test | 13 -
.../languages/bash/function_feature.test | 101 -
.../tests/languages/bash/keyword_feature.test | 20 -
.../tests/languages/bash/shebang_feature.test | 11 -
.../tests/languages/bash/string_feature.test | 67 -
.../languages/bash/variable_feature.test | 15 -
.../languages/basic/comment_feature.test | 13 -
.../languages/basic/function_feature.test | 309 -
.../languages/basic/keyword_feature.test | 213 -
.../tests/languages/basic/number_feature.test | 19 -
.../languages/basic/operator_feature.test | 21 -
.../tests/languages/basic/string_feature.test | 13 -
.../languages/batch/command_feature.test | 103 -
.../languages/batch/comment_feature.test | 18 -
.../tests/languages/batch/label_feature.test | 13 -
.../tests/languages/bison/c_feature.test | 56 -
.../languages/bison/comment_feature.test | 25 -
.../languages/bison/keyword_feature.test | 22 -
.../tests/languages/bison/number_feature.test | 15 -
.../languages/bison/property_feature.test | 21 -
.../tests/languages/bison/string_feature.test | 21 -
.../languages/brainfuck/all_feature.test | 19 -
.../tests/languages/bro/builtin_feature.test | 29 -
.../tests/languages/bro/comment_feature.test | 17 -
.../tests/languages/bro/function_feature.test | 21 -
.../tests/languages/bro/keyword_feature.test | 87 -
.../tests/languages/bro/string_feature.test | 23 -
.../tests/languages/bro/variable_feature.test | 25 -
.../tests/languages/c+pure/c_inclusion.test | 28 -
.../tests/languages/c/constant_feature.test | 37 -
.../tests/languages/c/keyword_feature.test | 29 -
.../tests/languages/c/macro_feature.test | 45 -
.../tests/languages/c/number_feature.test | 35 -
.../tests/languages/c/operator_feature.test | 61 -
.../tests/languages/cil/asm_reference.test | 11 -
.../tests/languages/cil/boolean.test | 14 -
.../tests/languages/cil/comment.test | 11 -
.../tests/languages/cil/instructions.test | 457 --
.../tests/languages/cil/keywords.test | 161 -
.../tests/languages/cil/strings.test | 11 -
.../languages/clike/boolean_feature.test | 12 -
.../languages/clike/class-name_feature.test | 53 -
.../languages/clike/comment_feature.test | 16 -
.../languages/clike/function_feature.test | 23 -
.../tests/languages/clike/issue1340.test | 13 -
.../languages/clike/keyword_feature.test | 30 -
.../tests/languages/clike/number_feature.test | 23 -
.../languages/clike/operator_feature.test | 21 -
.../tests/languages/clike/string_feature.test | 31 -
.../languages/clojure/boolean_feature.test | 15 -
.../languages/clojure/comment_feature.test | 13 -
.../languages/clojure/keyword_feature.test | 175 -
.../clojure/operator_and_punctuation.test | 20 -
.../languages/clojure/string_feature.test | 13 -
.../coffeescript_inclusion.test | 24 -
.../coffeescript_inclusion.test | 19 -
.../coffeescript/block-regex_feature.test | 33 -
.../coffeescript/class-member_feature.test | 13 -
.../coffeescript/comment_feature.test | 16 -
.../inline-javascript_feature.test | 22 -
.../coffeescript/keyword_feature.test | 41 -
.../coffeescript/property_feature.test | 15 -
.../coffeescript/string_feature.test | 64 -
.../languages/cpp+pure/cpp_inclusion.test | 18 -
.../tests/languages/cpp/boolean_feature.test | 13 -
.../languages/cpp/class-name_feature.test | 13 -
.../tests/languages/cpp/keyword_feature.test | 49 -
.../tests/languages/cpp/operator_feature.test | 73 -
.../languages/cpp/raw_string_feature.test | 18 -
.../languages/crystal/attribute_feature.test | 21 -
.../languages/crystal/expansion_feature.test | 37 -
.../languages/crystal/keyword_feature.test | 37 -
.../languages/crystal/number_feature.test | 23 -
.../csharp+aspnet/directive_feature.test | 70 -
.../languages/csharp/class-name_feature.test | 34 -
.../languages/csharp/generic_feature.test | 34 -
.../tests/languages/csharp/issue1091.test | 12 -
.../tests/languages/csharp/issue1365.test | 39 -
.../tests/languages/csharp/issue1371.test | 144 -
.../tests/languages/csharp/issue806.test | 12 -
.../languages/csharp/keyword_feature.test | 209 -
.../languages/csharp/number_feature.test | 17 -
.../languages/csharp/operator_feature.test | 60 -
.../csharp/preprocessor_feature.test | 35 -
.../languages/csharp/punctuation_feature.test | 27 -
.../languages/csharp/string_feature.test | 32 -
.../csp/directive_no_value_feature.test | 11 -
...ective_with_source_expression_feature.test | 12 -
.../tests/languages/csp/safe_feature.test | 19 -
.../tests/languages/csp/unsafe_feature.test | 15 -
.../css!+css-extras/entity_feature.test | 13 -
.../css!+css-extras/hexcode_feature.test | 17 -
.../css!+css-extras/number_feature.test | 17 -
.../css!+css-extras/operator_feature.test | 71 -
.../css!+css-extras/selector_feature.test | 58 -
.../css!+css-extras/unit_feature.test | 21 -
.../css!+css-extras/variable_feature.test | 54 -
.../languages/css+haml/css+haml_usage.test | 28 -
.../languages/css+http/css_inclusion.test | 25 -
.../languages/css+textile/css_inclusion.test | 117 -
.../tests/languages/css/atrule_feature.test | 47 -
.../tests/languages/css/comment_feature.test | 16 -
.../tests/languages/css/function_feature.test | 41 -
.../languages/css/important_feature.test | 27 -
.../tests/languages/css/property_feature.test | 29 -
.../tests/languages/css/selector_feature.test | 25 -
.../tests/languages/css/string_feature.test | 22 -
.../tests/languages/css/url_feature.test | 21 -
.../tests/languages/d/comment_feature.test | 27 -
.../tests/languages/d/keyword_feature.test | 251 -
.../tests/languages/d/number_feature.test | 55 -
.../tests/languages/d/operator_feature.test | 63 -
.../tests/languages/d/property_feature.test | 17 -
.../tests/languages/d/register_feature.test | 75 -
.../tests/languages/d/string_feature.test | 56 -
.../languages/d/token-string_feature.test | 13 -
.../tests/languages/dart/keyword_feature.test | 49 -
.../languages/dart/metadata_feature.test | 20 -
.../languages/dart/operator_feature.test | 33 -
.../tests/languages/dart/string_feature.test | 25 -
.../tests/languages/diff/coord_feature.test | 21 -
.../tests/languages/diff/diff_feature.test | 21 -
.../languages/django/comment_feature.test | 16 -
.../languages/django/property_feature.test | 64 -
.../languages/docker/comment_feature.test | 13 -
.../languages/docker/keyword_feature.test | 45 -
.../languages/docker/string_feature.test | 23 -
.../languages/eiffel/boolean_feature.test | 13 -
.../tests/languages/eiffel/char_feature.test | 15 -
.../languages/eiffel/class-name_feature.test | 15 -
.../languages/eiffel/comment_feature.test | 15 -
.../languages/eiffel/keyword_feature.test | 39 -
.../languages/eiffel/number_feature.test | 29 -
.../languages/eiffel/operator_feature.test | 19 -
.../languages/eiffel/string_feature.test | 34 -
.../tests/languages/elixir/atom_feature.test | 15 -
.../languages/elixir/attr-name_feature.test | 24 -
.../languages/elixir/attribute_feature.test | 19 -
.../languages/elixir/boolean_feature.test | 15 -
.../languages/elixir/capture_feature.test | 28 -
.../languages/elixir/comment_feature.test | 15 -
.../tests/languages/elixir/issue1392.test | 16 -
.../tests/languages/elixir/issue775.test | 17 -
.../languages/elixir/keyword_feature.test | 31 -
.../languages/elixir/number_feature.test | 27 -
.../languages/elixir/operator_feature.test | 41 -
.../tests/languages/elixir/regex_feature.test | 29 -
.../languages/elixir/string_feature.test | 115 -
.../tests/languages/elm/builtin_feature.test | 25 -
.../tests/languages/elm/char_feature.test | 19 -
.../tests/languages/elm/comment_feature.test | 14 -
.../tests/languages/elm/constant_feature.test | 15 -
.../languages/elm/hvariable_feature.test | 15 -
.../elm/import_statement_feature.test | 48 -
.../tests/languages/elm/keyword_feature.test | 19 -
.../tests/languages/elm/number_feature.test | 21 -
.../tests/languages/elm/operator_feature.test | 33 -
.../tests/languages/elm/string_feature.test | 21 -
.../tests/languages/erb/erb_feature.test | 36 -
.../languages/erb/erb_in_markup_feature.test | 48 -
.../tests/languages/erlang/atom_feature.test | 17 -
.../languages/erlang/boolean_feature.test | 13 -
.../languages/erlang/comment_feature.test | 11 -
.../languages/erlang/function_feature.test | 17 -
.../languages/erlang/keyword_feature.test | 15 -
.../languages/erlang/number_feature.test | 25 -
.../languages/erlang/operator_feature.test | 27 -
.../languages/erlang/string_feature.test | 13 -
.../languages/erlang/variable_feature.test | 17 -
.../flow/flow-punctuation_feature.test | 12 -
.../flow/function-variable_feature.test | 20 -
.../tests/languages/flow/keyword_feature.test | 39 -
.../tests/languages/flow/type_feature.test | 31 -
.../fortran+pure/fortran_inclusion.test | 18 -
.../languages/fortran/boolean_feature.test | 13 -
.../languages/fortran/comment_feature.test | 15 -
.../languages/fortran/keyword_feature.test | 199 -
.../languages/fortran/number_feature.test | 37 -
.../languages/fortran/operator_feature.test | 25 -
.../languages/fortran/string_feature.test | 31 -
.../languages/fsharp/annotation_feature.test | 35 -
.../languages/fsharp/class-name_feature.test | 86 -
.../languages/fsharp/comment_feature.test | 16 -
.../computation-expression_feature.test | 17 -
.../tests/languages/fsharp/issue1480.test | 36 -
.../languages/fsharp/keyword_feature.test | 73 -
.../languages/fsharp/number_feature.test | 65 -
.../languages/fsharp/operator_feature.test | 53 -
.../fsharp/preprocessor_feature.test | 22 -
.../languages/fsharp/string_feature.test | 47 -
.../languages/gcode/checksum_feature.test | 12 -
.../languages/gcode/comment_feature.test | 20 -
.../languages/gcode/keyword_feature.test | 23 -
.../languages/gcode/property_feature.test | 17 -
.../tests/languages/gcode/string_feature.test | 17 -
.../tests/languages/gedcom/level_feature.test | 20 -
.../languages/gedcom/line-value_feature.test | 29 -
.../languages/gedcom/pointer_feature.test | 23 -
.../tests/languages/gedcom/tag_feature.test | 25 -
.../languages/gherkin/atrule_feature.test | 1211 ----
.../languages/gherkin/comment_feature.test | 15 -
.../languages/gherkin/feature_feature.test | 196 -
.../languages/gherkin/outline_feature.test | 11 -
.../languages/gherkin/pystring_feature.test | 20 -
.../languages/gherkin/scenario_feature.test | 581 --
.../languages/gherkin/string_feature.test | 29 -
.../languages/gherkin/table_feature.test | 40 -
.../tests/languages/gherkin/tag_feature.test | 17 -
.../tests/languages/git/command_feature.test | 15 -
.../tests/languages/git/comment_feature.test | 17 -
.../languages/git/commit_sha1_feature.test | 15 -
.../tests/languages/git/coord_feature.test | 13 -
.../tests/languages/git/diff_feature.test | 31 -
.../tests/languages/git/string_feature.test | 17 -
.../tests/languages/glsl/comment_feature.test | 21 -
.../tests/languages/glsl/keyword_feature.test | 263 -
.../tests/languages/glsl/number_feature.test | 31 -
.../languages/glsl/preprocessor_feature.test | 35 -
.../tests/languages/go/boolean_feature.test | 19 -
.../tests/languages/go/builtin_feature.test | 79 -
.../tests/languages/go/keyword_feature.test | 59 -
.../tests/languages/go/number_feature.test | 43 -
.../tests/languages/go/operator_feature.test | 27 -
.../tests/languages/go/string_feature.test | 37 -
.../languages/graphql/attr-name_feature.test | 27 -
.../languages/graphql/boolean_feature.test | 13 -
.../languages/graphql/comment_feature.test | 13 -
.../languages/graphql/directive_feature.test | 13 -
.../languages/graphql/keyword_feature.test | 24 -
.../languages/graphql/number_feature.test | 23 -
.../languages/graphql/string_feature.test | 15 -
.../languages/graphql/variable_feature.test | 13 -
.../languages/groovy/annotation_feature.test | 17 -
.../tests/languages/groovy/issue1049.js | 8 -
.../languages/groovy/keyword_feature.test | 61 -
.../languages/groovy/number_feature.test | 43 -
.../languages/groovy/operator_feature.test | 45 -
.../languages/groovy/shebang_feature.test | 13 -
.../languages/groovy/spock-block_feature.test | 25 -
.../groovy/string-interpolation_feature.js | 28 -
.../languages/groovy/string_feature.test | 60 -
.../tests/languages/haml/code_feature.test | 19 -
.../tests/languages/haml/doctype_feature.test | 15 -
.../languages/haml/interpolation_feature.test | 21 -
.../haml/multiline-code_feature.test | 58 -
.../haml/multiline-comment_feature.test | 46 -
.../tests/languages/haml/tag_feature.test | 161 -
.../handlebars+pug/handlebars_inclusion.test | 15 -
.../languages/handlebars/block_feature.test | 23 -
.../languages/handlebars/boolean_feature.test | 17 -
.../languages/handlebars/comment_feature.test | 19 -
.../handlebars_in_markup_feature.test | 59 -
.../languages/handlebars/number_feature.test | 29 -
.../languages/handlebars/string_feature.test | 25 -
.../languages/haskell/builtin_feature.test | 137 -
.../tests/languages/haskell/char_feature.test | 17 -
.../languages/haskell/comment_feature.test | 14 -
.../languages/haskell/constant_feature.test | 15 -
.../languages/haskell/hvariable_feature.test | 15 -
.../haskell/import_statement_feature.test | 35 -
.../languages/haskell/keyword_feature.test | 19 -
.../languages/haskell/number_feature.test | 23 -
.../languages/haskell/operator_feature.test | 37 -
.../languages/haskell/string_feature.test | 19 -
.../tests/languages/haxe/keyword_feature.test | 93 -
.../languages/haxe/metadata_feature.test | 15 -
.../languages/haxe/operator_feature.test | 29 -
.../languages/haxe/preprocessor_feature.test | 17 -
.../tests/languages/haxe/regex_feature.test | 15 -
.../languages/haxe/reification_feature.test | 16 -
.../tests/languages/haxe/string_feature.test | 37 -
.../languages/hpkp/safe_maxage_feature.test | 12 -
.../languages/hpkp/sha256_pin_feature.test | 11 -
.../languages/hpkp/unsafe_maxage_feature.test | 12 -
.../hsts/include_subdomains_feature.test | 11 -
.../tests/languages/hsts/preload_feature.test | 11 -
.../languages/hsts/safe_maxage_feature.test | 12 -
.../languages/hsts/unsafe_maxage_feature.test | 12 -
.../languages/http/header-name_feature.test | 24 -
.../languages/http/request-line_feature.test | 56 -
.../http/response-status_feature.test | 29 -
.../languages/ichigojam/comment_feature.test | 17 -
.../languages/ichigojam/function_feature.test | 59 -
.../languages/ichigojam/keyword_feature.test | 119 -
.../languages/ichigojam/label_feature.test | 13 -
.../languages/ichigojam/number_feature.test | 23 -
.../languages/ichigojam/operator_feature.test | 36 -
.../languages/ichigojam/string_feature.test | 13 -
.../icon/builtin-keyword_feature.test | 91 -
.../tests/languages/icon/comment_feature.test | 13 -
.../languages/icon/directive_feature.test | 21 -
.../languages/icon/function_feature.test | 15 -
.../tests/languages/icon/keyword_feature.test | 67 -
.../tests/languages/icon/number_feature.test | 33 -
.../languages/icon/operator_feature.test | 69 -
.../tests/languages/icon/string_feature.test | 22 -
.../languages/inform7/comment_feature.test | 15 -
.../languages/inform7/keyword_feature.test | 85 -
.../languages/inform7/number_feature.test | 25 -
.../languages/inform7/position_feature.test | 73 -
.../languages/inform7/property_feature.test | 157 -
.../languages/inform7/string_feature.test | 49 -
.../languages/inform7/title_feature.test | 21 -
.../languages/inform7/variable_feature.test | 141 -
.../tests/languages/inform7/verb_feature.test | 213 -
.../tests/languages/ini/comment_feature.test | 13 -
.../languages/ini/key_value_feature.test | 21 -
.../tests/languages/ini/selector_feature.test | 13 -
.../tests/languages/io/comment_feature.test | 19 -
.../tests/languages/io/number_feature.test | 23 -
.../tests/languages/io/operator_feature.test | 26 -
.../tests/languages/io/string_feature.test | 18 -
.../tests/languages/j/adverb_feature.test | 19 -
.../tests/languages/j/comment_feature.test | 13 -
.../languages/j/conjunction_feature.test | 41 -
.../tests/languages/j/keyword_feature.test | 77 -
.../tests/languages/j/number_feature.test | 41 -
.../tests/languages/j/string_feature.test | 13 -
.../tests/languages/j/verb_feature.test | 93 -
.../languages/java/function_featrue.test | 32 -
.../languages/java/generics_feature.test | 67 -
.../tests/languages/java/issue1351.test | 27 -
.../tests/languages/java/keyword_feature.test | 59 -
.../tests/languages/java/module_feature.test | 158 -
.../tests/languages/java/number_feature.test | 60 -
.../languages/java/operator_feature.test | 37 -
.../tests/languages/java/package_feature.test | 80 -
.../javascript+haml/javascript_inclusion.test | 24 -
.../javascript+http/javascript_inclusion.test | 21 -
.../languages/javascript/boolean_feature.test | 13 -
.../javascript/class-method_feature.test | 59 -
.../javascript/constant_feature.test | 21 -
.../javascript/function-variable_feature.test | 104 -
.../javascript/function_feature.test | 29 -
.../tests/languages/javascript/issue1337.test | 11 -
.../tests/languages/javascript/issue1340.test | 15 -
.../tests/languages/javascript/issue1397.test | 21 -
.../tests/languages/javascript/issue1526.test | 35 -
.../languages/javascript/keyword_feature.test | 73 -
.../languages/javascript/number_feature.test | 36 -
.../javascript/operator_feature.test | 33 -
.../languages/javascript/regex_feature.test | 29 -
.../javascript/supposed-classes_feature.test | 30 -
.../javascript/supposed-function_feature.test | 38 -
.../javascript/template-string_feature.test | 49 -
.../javascript/try-catch_feature.test | 22 -
.../javastacktrace/more_feature.test | 22 -
.../javastacktrace/stack-frame_feature.test | 71 -
.../javastacktrace/summary_feature.test | 155 -
.../languages/jolie/deployment_features.test | 43 -
.../languages/jolie/keyword_feature.test | 129 -
.../tests/languages/jolie/number_feature.test | 19 -
.../languages/jolie/operator_feature.test | 42 -
.../json+http/json-suffix_inclusion.test | 21 -
.../languages/json+http/json_inclusion.test | 21 -
.../tests/languages/json/boolean_feature.test | 13 -
.../tests/languages/json/comment_feature.test | 27 -
.../tests/languages/json/null_feature.test | 11 -
.../tests/languages/json/number_feature.test | 27 -
.../languages/json/operator_feature.test | 11 -
.../languages/json/property_feature.test | 33 -
.../languages/json/punctuation_feature.test | 20 -
.../tests/languages/json/string_feature.test | 27 -
.../tests/languages/jsx/issue1103.test | 29 -
.../tests/languages/jsx/issue1235.test | 29 -
.../tests/languages/jsx/issue1236.test | 26 -
.../tests/languages/jsx/issue1294.test | 71 -
.../tests/languages/jsx/issue1335.test | 126 -
.../tests/languages/jsx/issue1342.test | 53 -
.../tests/languages/jsx/issue1356.test | 32 -
.../tests/languages/jsx/issue1364.test | 25 -
.../tests/languages/jsx/issue1408.test | 36 -
.../tests/languages/jsx/issue1421.test | 58 -
.../languages/jsx/plain-text_feature.test | 57 -
.../tests/languages/jsx/tag_feature.test | 83 -
.../languages/julia/boolean_feature.test | 13 -
.../languages/julia/comment_feature.test | 13 -
.../languages/julia/keyword_feature.test | 31 -
.../tests/languages/julia/number_feature.test | 33 -
.../languages/julia/operator_feature.test | 41 -
.../tests/languages/julia/string_feature.test | 29 -
.../languages/keyman/atrule_feature.test | 15 -
.../tests/languages/keyman/bold_feature.test | 59 -
.../languages/keyman/comment_feature.test | 13 -
.../languages/keyman/function_feature.test | 39 -
.../languages/keyman/keyword_feature.test | 21 -
.../languages/keyman/number_feature.test | 21 -
.../languages/keyman/operator_feature.test | 15 -
.../languages/keyman/string_feature.test | 17 -
.../tests/languages/keyman/tag_feature.test | 19 -
.../languages/kotlin/annotation_feature.test | 21 -
.../languages/kotlin/function_feature.test | 16 -
.../kotlin/interpolation_feature.test | 46 -
.../languages/kotlin/keyword_feature.test | 137 -
.../tests/languages/kotlin/label_feature.test | 15 -
.../languages/kotlin/number_feature.test | 39 -
.../languages/kotlin/operator_feature.test | 31 -
.../languages/kotlin/raw-string_feature.test | 18 -
.../tests/languages/latex/cdata_feature.test | 28 -
.../languages/latex/comment_feature.test | 13 -
.../languages/latex/equation_feature.test | 121 -
.../languages/latex/headline_feature.test | 39 -
.../languages/latex/keyword_feature.test | 32 -
.../tests/languages/latex/url_feature.test | 12 -
.../languages/less+haml/less_inclusion.test | 32 -
.../languages/less+pug/less_inclusion.test | 20 -
.../tests/languages/less/atrule_feature.test | 25 -
.../tests/languages/less/comment_feature.test | 18 -
.../languages/less/operator_feature.test | 14 -
.../languages/less/property_feature.test | 19 -
.../languages/less/selector_feature.test | 24 -
.../languages/liquid/function_feature.test | 39 -
.../languages/liquid/keyword_feature.test | 29 -
.../languages/liquid/number_feature.test | 27 -
.../languages/liquid/operator_feature.test | 33 -
.../tests/languages/lisp/boolean_feature.test | 17 -
.../tests/languages/lisp/car_feature.test | 13 -
.../tests/languages/lisp/comment_feature.test | 11 -
.../tests/languages/lisp/declare_feature.test | 16 -
.../tests/languages/lisp/defun_feature.test | 27 -
.../tests/languages/lisp/defvar_feature.test | 25 -
.../tests/languages/lisp/heading_feature.test | 11 -
.../languages/lisp/interactive_feature.test | 16 -
.../tests/languages/lisp/keyword_feature.test | 73 -
.../tests/languages/lisp/lambda-feature.test | 13 -
.../languages/lisp/lisp-property_feature.test | 15 -
.../tests/languages/lisp/number_boolean.test | 27 -
.../languages/lisp/punctuation_feature.test | 16 -
.../languages/lisp/quoted-symbol_feature.test | 17 -
.../tests/languages/lisp/splice_feature.test | 17 -
.../tests/languages/lisp/string_feature.test | 27 -
.../livescript/argument_feature.test | 17 -
.../languages/livescript/boolean_feature.test | 21 -
.../languages/livescript/comment_feature.test | 18 -
.../livescript/identifier_feature.test | 25 -
.../livescript/interpolated-string.test | 57 -
.../livescript/keyword-operator_feature.test | 57 -
.../languages/livescript/keyword_feature.test | 87 -
.../languages/livescript/number_feature.test | 21 -
.../livescript/operator_feature.test | 55 -
.../languages/livescript/regex_feature.test | 27 -
.../languages/livescript/string_feature.test | 32 -
.../languages/lolcode/boolean_feature.test | 13 -
.../languages/lolcode/comment_feature.test | 14 -
.../languages/lolcode/function_feature.test | 18 -
.../languages/lolcode/keyword_feature.test | 93 -
.../languages/lolcode/label_feature.test | 15 -
.../languages/lolcode/number_feature.test | 13 -
.../languages/lolcode/operator_feature.test | 39 -
.../languages/lolcode/string_feature.test | 36 -
.../languages/lolcode/symbol_feature.test | 27 -
.../languages/lolcode/variable_feature.test | 11 -
.../tests/languages/lua/comment_feature.test | 22 -
.../tests/languages/lua/function_feature.test | 17 -
.../tests/languages/lua/keyword_feature.test | 53 -
.../tests/languages/lua/number_feature.test | 35 -
.../tests/languages/lua/operator_feature.test | 25 -
.../tests/languages/lua/string_feature.test | 36 -
.../languages/makefile/builtin_feature.test | 15 -
.../languages/makefile/comment_feature.test | 16 -
.../languages/makefile/keyword_feature.test | 73 -
.../languages/makefile/operator_feature.test | 15 -
.../languages/makefile/string_feature.test | 23 -
.../languages/makefile/symbol_feature.test | 18 -
.../languages/makefile/variable_feature.test | 19 -
.../markdown+haml/markdown_inclusion.test | 32 -
.../markdown+pug/markdown_inclusion.test | 18 -
.../markdown/blockquote_feature.test | 15 -
.../languages/markdown/bold_feature.test | 82 -
.../languages/markdown/code_feature.test | 33 -
.../tests/languages/markdown/hr_feature.test | 17 -
.../languages/markdown/italic_feature.test | 46 -
.../languages/markdown/list_feature.test | 22 -
.../languages/markdown/strike_feature.test | 70 -
.../languages/markdown/title_feature.test | 42 -
.../markdown/url-reference_feature.test | 56 -
.../tests/languages/markdown/url_feature.test | 25 -
.../markup!+css+javascript/issue1240.test | 38 -
.../languages/markup!+css/css_inclusion.test | 71 -
.../javascript_inclusion.test | 60 -
.../markup+actionscript/xml_feature.test | 64 -
.../markup+css+wiki/table-tag_feature.test | 147 -
.../languages/markup+haml/markup_feature.test | 11 -
.../languages/markup+http/html_inclusion.test | 30 -
.../markup+http/xml-suffix_inclusion.test | 30 -
.../languages/markup+http/xml_inclusion.test | 30 -
.../script_feature.test | 57 -
.../markup+php/php_in_markup_feature.test | 129 -
.../languages/markup+pug/markup_feature.test | 29 -
.../markup+tt2/tt2_in_markup_feature.test | 89 -
.../tests/languages/markup/cdata_feature.test | 15 -
.../languages/markup/comment_feature.test | 16 -
.../languages/markup/doctype_feature.test | 16 -
.../tests/languages/markup/entity_feature.js | 4 -
.../languages/markup/entity_feature.test | 14 -
.../tests/languages/markup/issue585.test | 63 -
.../tests/languages/markup/issue888.test | 18 -
.../languages/markup/prolog_feature.test | 16 -
.../markup/tag_attribute_feature.test | 110 -
.../tests/languages/markup/tag_feature.test | 81 -
.../languages/matlab/comment_feature.test | 20 -
.../languages/matlab/function_feature.test | 13 -
.../languages/matlab/keyword_feature.test | 21 -
.../languages/matlab/number_feature.test | 27 -
.../languages/matlab/operator_feature.test | 29 -
.../languages/matlab/string_feature.test | 15 -
.../tests/languages/mel/code_feature.test | 16 -
.../tests/languages/mel/comment_feature.test | 13 -
.../tests/languages/mel/flag_feature.test | 15 -
.../tests/languages/mel/function_feature.test | 2453 --------
.../tests/languages/mel/keyword_feature.test | 47 -
.../tests/languages/mel/number_feature.test | 15 -
.../tests/languages/mel/operator_feature.test | 33 -
.../tests/languages/mel/string_feature.test | 13 -
.../tests/languages/mel/variable_feature.test | 15 -
.../languages/mizar/comment_feature.test | 11 -
.../languages/mizar/keyword_feature.test | 245 -
.../tests/languages/mizar/number_feature.test | 15 -
.../languages/mizar/operator_feature.test | 17 -
.../languages/mizar/parameter_feature.test | 17 -
.../languages/mizar/variable_feature.test | 17 -
.../languages/monkey/comment_feature.test | 21 -
.../languages/monkey/function_feature.test | 13 -
.../languages/monkey/keyword_feature.test | 125 -
.../languages/monkey/number_feature.test | 19 -
.../languages/monkey/operator_feature.test | 41 -
.../monkey/preprocessor_feature.test | 15 -
.../languages/monkey/string_feature.test | 13 -
.../languages/monkey/type-char_feature.test | 17 -
.../languages/n4js/annotation_feature.test | 53 -
.../tests/languages/n4js/keyword_feature.test | 121 -
.../tests/languages/nasm/comment_feature.test | 13 -
.../tests/languages/nasm/keyword_feature.test | 30 -
.../tests/languages/nasm/label_feature.test | 15 -
.../tests/languages/nasm/number_feature.test | 97 -
.../languages/nasm/operator_feature.test | 17 -
.../languages/nasm/register_feature.test | 43 -
.../tests/languages/nasm/string_feature.test | 21 -
.../languages/nginx/comment_feature.test | 13 -
.../languages/nginx/keyword_feature.test | 719 ---
.../languages/nginx/variable_feature.test | 13 -
.../tests/languages/nim/comment_feature.test | 13 -
.../tests/languages/nim/function_feature.test | 17 -
.../tests/languages/nim/keyword_feature.test | 123 -
.../tests/languages/nim/number_feature.test | 31 -
.../tests/languages/nim/operator_feature.test | 39 -
.../tests/languages/nim/string_feature.test | 38 -
.../languages/nix/antiquotation_feature.test | 14 -
.../tests/languages/nix/boolean_feature.test | 13 -
.../tests/languages/nix/comment_feature.test | 18 -
.../tests/languages/nix/function_feature.test | 133 -
.../tests/languages/nix/keyword_feature.test | 15 -
.../tests/languages/nix/number_feature.test | 15 -
.../tests/languages/nix/operator_feature.test | 25 -
.../tests/languages/nix/string_feature.test | 56 -
.../tests/languages/nix/url_feature.test | 21 -
.../tests/languages/nsis/comment_feature.test | 18 -
.../languages/nsis/constant_feature.test | 23 -
.../languages/nsis/important_feature.test | 75 -
.../tests/languages/nsis/keyword_feature.test | 455 --
.../tests/languages/nsis/number_feature.test | 19 -
.../languages/nsis/operator_feature.test | 21 -
.../languages/nsis/property_feature.test | 115 -
.../tests/languages/nsis/string_feature.test | 17 -
.../languages/nsis/variable_feature.test | 13 -
.../languages/objectivec/keyword_feature.test | 59 -
.../objectivec/operator_feature.test | 25 -
.../languages/objectivec/string_feature.test | 34 -
.../languages/ocaml/boolean_feature.test | 13 -
.../languages/ocaml/comment_feature.test | 14 -
.../languages/ocaml/directive_feature.test | 15 -
.../languages/ocaml/keyword_feature.test | 101 -
.../tests/languages/ocaml/number_feature.test | 25 -
.../languages/ocaml/operator_feature.test | 31 -
.../tests/languages/ocaml/string_feature.test | 25 -
.../tests/languages/ocaml/type_feature.test | 17 -
.../languages/opencl+c/boolean_feature.test | 13 -
.../languages/opencl+c/constant_feature.test | 859 ---
.../languages/opencl+c/function_feature.test | 227 -
.../languages/opencl+c/type_feature.test | 219 -
.../languages/opencl+cpp/type_feature.test | 83 -
.../languages/opencl/constant_feature.test | 185 -
.../languages/opencl/function_feature.test | 601 --
.../languages/opencl/keyword_feature.test | 419 --
.../tests/languages/oz/atom_feature.test | 16 -
.../tests/languages/oz/attr-name_feature.test | 14 -
.../tests/languages/oz/comment_feature.test | 18 -
.../tests/languages/oz/function_feature.test | 13 -
.../tests/languages/oz/keyword_feature.test | 103 -
.../tests/languages/oz/number_feature.test | 35 -
.../tests/languages/oz/operator_feature.test | 35 -
.../tests/languages/oz/string_feature.test | 16 -
.../tests/languages/oz/variable_feature.test | 15 -
.../languages/parigp/comment_feature.test | 18 -
.../languages/parigp/function_feature.test | 13 -
.../languages/parigp/keyword_feature.test | 103 -
.../languages/parigp/number_feature.test | 39 -
.../languages/parigp/operator_feature.test | 155 -
.../languages/parigp/string_feature.test | 13 -
.../languages/parser/boolean_feature.test | 21 -
.../languages/parser/escape_feature.test | 68 -
.../languages/parser/expression_feature.test | 58 -
.../languages/parser/function_feature.test | 48 -
.../languages/parser/keyword_feature.test | 70 -
.../languages/parser/number_feature.test | 51 -
.../languages/parser/operator_feature.test | 257 -
.../parser/parser-comment_feature.test | 17 -
.../languages/parser/string_feature.test | 47 -
.../languages/parser/variable_feature.test | 55 -
.../languages/pascal/comment_feature.test | 23 -
.../languages/pascal/keyword_feature.test | 143 -
.../languages/pascal/number_feature.test | 25 -
.../languages/pascal/operator_feature.test | 31 -
.../languages/pascal/string_feature.test | 21 -
.../tests/languages/perl/comment_feature.test | 17 -
.../languages/perl/filehandle_feature.test | 17 -
.../languages/perl/function_feature.test | 13 -
.../tests/languages/perl/keyword_feature.test | 29 -
.../tests/languages/perl/number_feature.test | 33 -
.../languages/perl/operator_feature.test | 71 -
.../tests/languages/perl/regex_feature.test | 129 -
.../tests/languages/perl/string_feature.test | 130 -
.../languages/perl/variable_feature.test | 47 -
.../tests/languages/perl/vstring_feature.test | 13 -
.../php!+php-extras/global_feature.test | 37 -
.../php!+php-extras/scope_feature.test | 27 -
.../php!+php-extras/this_feature.test | 11 -
.../tests/languages/php/comment_feature.test | 20 -
.../tests/languages/php/constant_feature.test | 15 -
.../languages/php/delimiter_feature.test | 24 -
.../tests/languages/php/keyword_feature.test | 76 -
.../tests/languages/php/package_feature.test | 29 -
.../tests/languages/php/property_feature.test | 19 -
.../languages/php/shell-comment_feature.test | 13 -
.../php/string-interpolation_feature.test | 140 -
.../tests/languages/php/string_feature.test | 56 -
.../tests/languages/php/variable_feature.test | 19 -
.../languages/plsql/comment_feature.test | 18 -
.../languages/plsql/keyword_feature.test | 415 --
.../languages/plsql/operator_feature.test | 11 -
.../languages/powershell/boolean_feature.test | 18 -
.../languages/powershell/comment_feature.test | 21 -
.../powershell/function_feature.test | 398 --
.../tests/languages/powershell/issue1407.test | 43 -
.../languages/powershell/keyword_feature.test | 46 -
.../powershell/namespace_feature.test | 18 -
.../powershell/operator_feature.test | 55 -
.../languages/powershell/string_feature.test | 78 -
.../powershell/variable_feature.test | 15 -
.../processing/constant_feature.test | 13 -
.../processing/function_feature.test | 13 -
.../languages/processing/keyword_feature.test | 59 -
.../processing/operator_feature.test | 31 -
.../languages/processing/type_feature.test | 31 -
.../languages/prolog/builtin_feature.test | 17 -
.../languages/prolog/comment_feature.test | 16 -
.../languages/prolog/function_feature.test | 17 -
.../languages/prolog/number_feature.test | 15 -
.../languages/prolog/operator_feature.test | 29 -
.../languages/prolog/string_feature.test | 27 -
.../languages/prolog/variable_feature.test | 15 -
.../languages/properties/comment_feature.test | 17 -
.../properties/key_value_feature.test | 36 -
.../languages/protobuf/keyword_feature.test | 40 -
.../languages/protobuf/string_feature.test | 23 -
.../tests/languages/pug/code_feature.test | 36 -
.../tests/languages/pug/comment_feature.test | 22 -
.../tests/languages/pug/doctype_feature.test | 15 -
.../languages/pug/flow-control_feature.test | 75 -
.../tests/languages/pug/keyword_feature.test | 27 -
.../tests/languages/pug/mixin_feature.test | 35 -
.../pug/multiline-plain-text_feature.test | 30 -
.../pug/multiline-script_feature.test | 58 -
.../languages/pug/plain-text_feature.test | 19 -
.../tests/languages/pug/script_feature.test | 38 -
.../tests/languages/pug/tag_feature.test | 97 -
.../languages/puppet/attr-name_feature.test | 19 -
.../languages/puppet/boolean_feature.test | 13 -
.../languages/puppet/comment_feature.test | 22 -
.../languages/puppet/datatype_feature.test | 63 -
.../languages/puppet/function_feature.test | 37 -
.../languages/puppet/heredoc_feature.test | 51 -
.../puppet/interpolation_feature.test | 54 -
.../languages/puppet/keyword_feature.test | 47 -
.../languages/puppet/number_feature.test | 25 -
.../languages/puppet/operator_feature.test | 29 -
.../tests/languages/puppet/regex_feature.test | 32 -
.../languages/puppet/string_feature.test | 36 -
.../languages/puppet/variable_feature.test | 15 -
.../tests/languages/pure/comment_feature.test | 20 -
.../languages/pure/function_feature.test | 619 --
.../tests/languages/pure/keyword_feature.test | 113 -
.../tests/languages/pure/number_feature.test | 31 -
.../languages/pure/operator_feature.test | 29 -
.../tests/languages/pure/special_feature.test | 15 -
.../tests/languages/pure/string_feature.test | 13 -
.../languages/python/boolean_feature.test | 15 -
.../languages/python/builtin_feature.test | 56 -
.../languages/python/class-name_feature.test | 15 -
.../languages/python/comment_feature.test | 13 -
.../languages/python/decorator_feature.test | 28 -
.../languages/python/function_feature.test | 17 -
.../tests/languages/python/issue1355.test | 24 -
.../languages/python/keyword_feature.test | 31 -
.../languages/python/number_feature.test | 27 -
.../languages/python/operator_feature.test | 29 -
.../python/string-interpolation_feature.test | 147 -
.../languages/python/string_feature.test | 29 -
.../python/triple-quoted-string_feature.test | 21 -
.../tests/languages/q/adverb_feature.test | 17 -
.../tests/languages/q/comment_feature.test | 24 -
.../tests/languages/q/datetime_feature.test | 39 -
.../tests/languages/q/keyword_feature.test | 371 --
.../tests/languages/q/number_feature.test | 33 -
.../tests/languages/q/string_feature.test | 13 -
.../tests/languages/q/symbol_feature.test | 17 -
.../tests/languages/q/verb_feature.test | 35 -
.../tests/languages/qore/boolean_feature.test | 13 -
.../tests/languages/qore/comment_feature.test | 22 -
.../languages/qore/function_feature.test | 15 -
.../tests/languages/qore/keyword_feature.test | 63 -
.../tests/languages/qore/number_feature.test | 21 -
.../languages/qore/operator_feature.test | 37 -
.../tests/languages/qore/string_feature.test | 19 -
.../languages/qore/variable_feature.test | 15 -
.../tests/languages/r/boolean_feature.test | 13 -
.../tests/languages/r/comment_feature.test | 13 -
.../tests/languages/r/ellipsis_feature.test | 15 -
.../tests/languages/r/keyword_feature.test | 25 -
.../tests/languages/r/number_feature.test | 39 -
.../tests/languages/r/operator_feature.test | 29 -
.../languages/r/percent-operator_feature.test | 15 -
.../tests/languages/r/string_feature.test | 17 -
.../languages/reason/character_feature.test | 19 -
.../languages/reason/class-name_feature.test | 15 -
.../languages/reason/comment_feature.test | 20 -
.../languages/reason/constructor_feature.test | 15 -
.../languages/reason/keyword_feature.test | 103 -
.../tests/languages/reason/label_feature.test | 13 -
.../languages/reason/operator_feature.test | 31 -
.../languages/reason/string_feature.test | 13 -
.../rest/command-line-option_feature.test | 37 -
.../tests/languages/rest/comment_feature.test | 24 -
.../languages/rest/directive_feature.test | 33 -
.../languages/rest/doctest-block_feature.test | 22 -
.../tests/languages/rest/field_feature.test | 19 -
.../tests/languages/rest/hr_feature.test | 112 -
.../tests/languages/rest/inline_feature.test | 55 -
.../languages/rest/link-target_feature.test | 90 -
.../tests/languages/rest/link_feature.test | 33 -
.../languages/rest/list-bullet_feature.test | 45 -
.../languages/rest/literal-block_feature.test | 27 -
.../rest/quoted-literal-block_feature.test | 333 --
.../rest/substitution-def_feature.test | 69 -
.../tests/languages/rest/table_feature.test | 64 -
.../tests/languages/rest/title_feature.test | 585 --
.../tests/languages/rip/boolean_feature.test | 13 -
.../tests/languages/rip/builtin_feature.test | 13 -
.../languages/rip/character_feature.test | 14 -
.../tests/languages/rip/comment_feature.test | 13 -
.../languages/rip/date_time_feature.test | 23 -
.../tests/languages/rip/keyword_feature.test | 21 -
.../tests/languages/rip/number_feature.test | 21 -
.../languages/rip/reference_feature.test | 13 -
.../tests/languages/rip/regex_feature.test | 17 -
.../tests/languages/rip/string_feature.test | 17 -
.../tests/languages/rip/symbol_feature.test | 15 -
.../languages/roboconf/comment_feature.test | 13 -
.../languages/roboconf/component_feature.test | 13 -
.../languages/roboconf/keyword_feature.test | 19 -
.../languages/roboconf/optional_feature.test | 11 -
.../languages/roboconf/property_feature.test | 17 -
.../languages/roboconf/value_feature.test | 20 -
.../languages/roboconf/wildcard_feature.test | 12 -
.../tests/languages/ruby/builtin_feature.test | 29 -
.../tests/languages/ruby/comment_feature.test | 22 -
.../languages/ruby/constant_feature.test | 21 -
.../tests/languages/ruby/issue1336.test | 15 -
.../tests/languages/ruby/keyword_feature.test | 103 -
.../ruby/method_definition_feature.test | 82 -
.../tests/languages/ruby/regex_feature.test | 45 -
.../tests/languages/ruby/string_feature.test | 287 -
.../tests/languages/ruby/symbol_feature.test | 17 -
.../languages/ruby/variable_feature.test | 27 -
.../languages/rust/attribute_feature.test | 13 -
.../tests/languages/rust/char_feature.test | 13 -
.../rust/closure-params_feature.test | 30 -
.../tests/languages/rust/comment_feature.test | 18 -
.../languages/rust/function_feature.test | 23 -
.../tests/languages/rust/issue1339.test | 49 -
.../tests/languages/rust/issue1353.test | 16 -
.../tests/languages/rust/keyword_feature.test | 39 -
.../rust/lifetime-annotation_feature.test | 15 -
.../languages/rust/macro-rules_feature.test | 15 -
.../tests/languages/rust/number_feature.test | 47 -
.../languages/rust/operator_feature.test | 35 -
.../tests/languages/rust/string_feature.test | 35 -
.../tests/languages/sas/comment_feature.test | 17 -
.../languages/sas/datalines_feature.test | 38 -
.../tests/languages/sas/datetime_feature.test | 15 -
.../tests/languages/sas/keyword_feature.test | 13 -
.../tests/languages/sas/number_feature.test | 21 -
.../tests/languages/sas/operator_feature.test | 37 -
.../tests/languages/sas/string_feature.test | 23 -
.../languages/sass/atrule-line_feature.test | 35 -
.../tests/languages/sass/comment_feature.test | 23 -
.../languages/sass/property-line_feature.test | 47 -
.../languages/sass/selector_feature.test | 24 -
.../languages/sass/variable-line_feature.test | 29 -
.../languages/scala/builtin_feature.test | 17 -
.../languages/scala/keyword_feature.test | 35 -
.../tests/languages/scala/number_feature.test | 27 -
.../tests/languages/scala/string_feature.test | 34 -
.../tests/languages/scala/symbol_feature.test | 15 -
.../languages/scheme/boolean_feature.test | 13 -
.../languages/scheme/builtin_feature.test | 53 -
.../languages/scheme/character_feature.test | 19 -
.../languages/scheme/comment_feature.test | 13 -
.../languages/scheme/function_feature.test | 21 -
.../tests/languages/scheme/issue1331.test | 12 -
.../languages/scheme/keyword_feature.test | 57 -
.../languages/scheme/number_feature.test | 19 -
.../languages/scheme/operator_feature.test | 31 -
.../languages/scheme/string_feature.test | 17 -
.../languages/scss+haml/scss_inclusion.test | 40 -
.../languages/scss+pug/scss_inclusion.test | 17 -
.../tests/languages/scss/atrule_feature.test | 20 -
.../tests/languages/scss/boolean_feature.test | 13 -
.../tests/languages/scss/comment_feature.test | 19 -
.../tests/languages/scss/keyword_feature.test | 28 -
.../tests/languages/scss/null_feature.test | 11 -
.../languages/scss/operator_feature.test | 38 -
.../languages/scss/placeholder_feature.test | 15 -
.../languages/scss/property_feature.test | 23 -
.../languages/scss/selector_feature.test | 23 -
.../languages/scss/statement_feature.test | 21 -
.../tests/languages/scss/url_feature.test | 19 -
.../languages/scss/variable_feature.test | 21 -
.../smalltalk/block-arguments_feature.test | 26 -
.../smalltalk/character_feature.test | 17 -
.../languages/smalltalk/comment_feature.test | 14 -
.../languages/smalltalk/keyword_feature.test | 13 -
.../languages/smalltalk/number_feature.test | 23 -
.../languages/smalltalk/operator_feature.test | 29 -
.../languages/smalltalk/string_feature.test | 14 -
.../languages/smalltalk/symbol_feature.test | 21 -
.../temporary-variables_feature.test | 25 -
.../languages/smarty/attr-name_feature.test | 36 -
.../languages/smarty/comment_feature.test | 14 -
.../languages/smarty/function_feature.test | 41 -
.../languages/smarty/keyword_feature.test | 51 -
.../languages/smarty/number_feature.test | 45 -
.../languages/smarty/operator_feature.test | 187 -
.../smarty/smarty_in_markup_feature.test | 55 -
.../languages/smarty/string_feature.test | 33 -
.../languages/smarty/variable_feature.test | 56 -
.../tests/languages/soy/boolean_feature.test | 27 -
.../tests/languages/soy/command-arg.test | 84 -
.../tests/languages/soy/comment_feature.test | 25 -
.../tests/languages/soy/function_feature.test | 86 -
.../tests/languages/soy/keyword_feature.test | 338 --
.../tests/languages/soy/literal_feature.test | 73 -
.../tests/languages/soy/number_feature.test | 63 -
.../tests/languages/soy/operator_feature.test | 121 -
.../languages/soy/parameter_feature.test | 72 -
.../tests/languages/soy/property_feature.test | 54 -
.../languages/soy/soy_in_markup_feature.test | 68 -
.../tests/languages/soy/string_feature.test | 47 -
.../tests/languages/soy/variable_feature.test | 86 -
.../tests/languages/sql/boolean_feature.test | 15 -
.../tests/languages/sql/comment_feature.test | 26 -
.../tests/languages/sql/function_feature.test | 39 -
.../tests/languages/sql/keyword_feature.test | 717 ---
.../tests/languages/sql/number_feature.test | 15 -
.../tests/languages/sql/operator_feature.test | 49 -
.../tests/languages/sql/string_feature.test | 27 -
.../tests/languages/sql/variable_feature.test | 26 -
.../stylus+pug/stylus_inclusion.test | 20 -
.../stylus/atrule-declaration_feature.test | 31 -
.../languages/stylus/boolean_feature.test | 21 -
.../languages/stylus/comment_feature.test | 18 -
.../tests/languages/stylus/func_feature.test | 51 -
.../languages/stylus/hexcode_feature.test | 29 -
.../languages/stylus/important_feature.test | 22 -
.../languages/stylus/keyword_feature.test | 44 -
.../languages/stylus/number_feature.test | 32 -
.../languages/stylus/operator_feature.test | 273 -
.../stylus/property-declaration_feature.test | 52 -
.../languages/stylus/selector_feature.test | 49 -
.../languages/stylus/string_feature.test | 33 -
.../tests/languages/stylus/url_feature.test | 21 -
.../stylus/variable-declaration_feature.test | 33 -
.../tests/languages/swift/atrule_feature.test | 33 -
.../languages/swift/builtin_feature.test | 53 -
.../languages/swift/constant_feature.test | 19 -
.../languages/swift/keyword_feature.test | 165 -
.../tests/languages/swift/number_feature.test | 25 -
.../tests/languages/swift/string_feature.test | 47 -
.../tests/languages/tap/bail_out_feature.test | 13 -
.../languages/tap/directive_feature.test | 15 -
.../languages/tap/pass_fail_feature.test | 17 -
.../tests/languages/tap/plan_feature.test | 13 -
.../tests/languages/tap/pragma_feature.test | 13 -
.../tests/languages/tap/version_feature.test | 11 -
.../tests/languages/tap/yamlish_feature.test | 50 -
.../tests/languages/tcl/builtin_feature.test | 35 -
.../tests/languages/tcl/comment_feature.test | 13 -
.../tests/languages/tcl/function_feature.test | 15 -
.../tests/languages/tcl/keyword_feature.test | 213 -
.../tests/languages/tcl/operator_feature.test | 45 -
.../tests/languages/tcl/scope_feature.test | 15 -
.../tests/languages/tcl/string_feature.test | 16 -
.../tests/languages/tcl/variable_feature.test | 31 -
.../languages/textile/acronym_feature.test | 15 -
.../languages/textile/block-tag_feature.test | 131 -
.../languages/textile/footnote_feature.test | 15 -
.../languages/textile/image_feature.test | 71 -
.../languages/textile/inline_feature.test | 166 -
.../languages/textile/link-ref_feature.test | 25 -
.../tests/languages/textile/link_feature.test | 44 -
.../tests/languages/textile/list_feature.test | 36 -
.../tests/languages/textile/mark_feature.test | 17 -
.../languages/textile/table_feature.test | 177 -
.../tests/languages/toml/boolean_feature.test | 13 -
.../tests/languages/toml/comment_feature.test | 11 -
.../tests/languages/toml/date_feature.test | 33 -
.../tests/languages/toml/key_feature.test | 42 -
.../tests/languages/toml/number_feature.test | 79 -
.../tests/languages/toml/string_feature.test | 29 -
.../tests/languages/toml/table_feature.test | 20 -
.../tests/languages/tsx/tag_feature.test | 105 -
.../tests/languages/tt2/comment_feature.test | 36 -
.../languages/tt2/delimiter_feature.test | 18 -
.../tests/languages/tt2/keyword_feature.test | 130 -
.../tests/languages/tt2/operator_feature.test | 69 -
.../tt2/string-interpolation_feature.test | 21 -
.../tests/languages/tt2/string_feature.test | 35 -
.../tests/languages/tt2/variable_feature.test | 36 -
.../languages/twig+pug/twig_inclusion.test | 19 -
.../tests/languages/twig/boolean_feature.test | 27 -
.../tests/languages/twig/comment_feature.test | 16 -
.../tests/languages/twig/keyword_feature.test | 53 -
.../tests/languages/twig/number_feature.test | 45 -
.../languages/twig/operator_feature.test | 179 -
.../tests/languages/twig/string_feature.test | 33 -
.../languages/typescript/builtin_feature.test | 31 -
.../languages/typescript/keyword_feature.test | 129 -
.../languages/vala/class-name_feature.test | 37 -
.../tests/languages/vala/keyword_feature.test | 189 -
.../tests/languages/vala/number_feature.test | 27 -
.../languages/vala/operator_feature.test | 63 -
.../languages/vala/punctuation_feature.test | 22 -
.../tests/languages/vala/string_feature.test | 64 -
.../languages/vbnet/comment_feature.test | 18 -
.../languages/vbnet/keyword_feature.test | 443 --
.../languages/velocity/directive_feature.test | 417 --
.../languages/velocity/unparsed_feature.test | 29 -
.../languages/velocity/variable_feature.test | 147 -
.../velocity/velocity-comment_feature.test | 18 -
.../languages/verilog/comment_feature.test | 18 -
.../languages/verilog/constant_feature.test | 13 -
.../languages/verilog/function_feature.test | 15 -
.../languages/verilog/important_feature.test | 27 -
.../languages/verilog/keyword_feature.test | 443 --
.../languages/verilog/number_feature.test | 39 -
.../languages/verilog/operator_feature.test | 39 -
.../languages/verilog/property_feature.test | 11 -
.../languages/verilog/string_feature.test | 16 -
.../tests/languages/vhdl/boolean_feature.test | 13 -
.../tests/languages/vhdl/comment_feature.test | 13 -
.../languages/vhdl/constant_feature.test | 13 -
.../languages/vhdl/function_feature.test | 29 -
.../tests/languages/vhdl/keyword_feature.test | 229 -
.../tests/languages/vhdl/number_feature.test | 37 -
.../languages/vhdl/operator_feature.test | 29 -
.../tests/languages/vhdl/string_feature.test | 16 -
.../languages/vhdl/vhdl-vectors_feature.test | 21 -
.../tests/languages/vim/builtin_feature.test | 2289 --------
.../tests/languages/vim/comment_feature.test | 13 -
.../tests/languages/vim/function_feature.test | 13 -
.../tests/languages/vim/keyword_feature.test | 1661 ------
.../tests/languages/vim/number_feature.test | 15 -
.../tests/languages/vim/operator_feature.test | 37 -
.../tests/languages/vim/string_feature.test | 19 -
.../visual-basic/boolean_feature.test | 15 -
.../visual-basic/comment_feature.test | 25 -
.../languages/visual-basic/date_feature.test | 23 -
.../visual-basic/directive_feature.test | 23 -
.../visual-basic/keyword_feature.test | 307 -
.../visual-basic/number_feature.test | 37 -
.../visual-basic/operator_feature.test | 37 -
.../visual-basic/string_feature.test | 35 -
.../tests/languages/wasm/comment_feature.test | 22 -
.../tests/languages/wasm/keyword_feature.test | 407 --
.../tests/languages/wasm/number_feature.test | 61 -
.../tests/languages/wasm/string_feature.test | 22 -
.../languages/wasm/variable_feature.test | 17 -
.../languages/wiki/block-comment_feature.test | 16 -
.../languages/wiki/emphasis_feature.test | 27 -
.../tests/languages/wiki/heading_feature.test | 33 -
.../tests/languages/wiki/hr_feature.test | 13 -
.../tests/languages/wiki/nowiki_feature.test | 63 -
.../tests/languages/wiki/symbol_feature.test | 17 -
.../tests/languages/wiki/url_feature.test | 29 -
.../languages/wiki/variable_feature.test | 19 -
.../languages/xeora/constant_feature.test | 15 -
.../xeora/directive-block-close_feature.test | 12 -
.../xeora/directive-block-open_feature.test | 30 -
.../directive-block-separator_feature.test | 17 -
.../xeora/directive-inline_feature.test | 21 -
.../xeora/function-block_feature.test | 43 -
.../xeora/function-inline_feature.test | 31 -
.../languages/xeora/variable_feature.test | 36 -
.../tests/languages/xojo/comment_feature.test | 15 -
.../tests/languages/xojo/keyword_feature.test | 125 -
.../tests/languages/xojo/number_feature.test | 27 -
.../languages/xojo/operator_feature.test | 27 -
.../tests/languages/xojo/string_feature.test | 15 -
.../tests/languages/xojo/symbol_feature.test | 19 -
.../tests/languages/xquery/axis_feature.test | 33 -
.../languages/xquery/builtin_feature.test | 122 -
.../languages/xquery/extension_feature.test | 11 -
.../languages/xquery/function_feature.test | 43 -
.../xquery/keyword-operator_feature.test | 43 -
.../languages/xquery/keyword_feature.test | 119 -
.../languages/xquery/number_feature.test | 17 -
.../languages/xquery/operator_feature.test | 21 -
.../languages/xquery/plain-text_feature.test | 71 -
.../languages/xquery/string_feature.test | 25 -
.../tests/languages/xquery/tag_feature.test | 133 -
.../languages/xquery/variable_feature.test | 15 -
.../xquery/xquery-attribute_feature.test | 18 -
.../xquery/xquery-comment_feature.test | 19 -
.../xquery/xquery-element_feature.test | 18 -
.../tests/languages/yaml/boolean_feature.test | 17 -
.../tests/languages/yaml/comment_feature.test | 13 -
.../languages/yaml/datetime_feature.test | 31 -
.../languages/yaml/directive_feature.test | 13 -
.../languages/yaml/important_feature.test | 19 -
.../tests/languages/yaml/key_feature.test | 15 -
.../tests/languages/yaml/null_feature.test | 17 -
.../tests/languages/yaml/number_feature.test | 38 -
.../tests/languages/yaml/scalar_feature.test | 23 -
.../tests/languages/yaml/string_feature.test | 29 -
.../tests/languages/yaml/tag_feature.test | 15 -
docs/_style/prism-master/tests/run.js | 45 -
.../prism-master/tests/testrunner-tests.js | 166 -
docs/_style/prism-master/themes/prism-coy.css | 225 -
.../_style/prism-master/themes/prism-dark.css | 128 -
.../prism-master/themes/prism-funky.css | 116 -
.../prism-master/themes/prism-okaidia.css | 122 -
.../themes/prism-solarizedlight.css | 149 -
.../prism-master/themes/prism-tomorrow.css | 121 -
.../prism-master/themes/prism-twilight.css | 198 -
docs/_style/prism-master/themes/prism.css | 138 -
docs/_style/prism-master/utopia.js | 463 --
.../prism-master/vendor/FileSaver.min.js | 2 -
docs/_style/prism-master/vendor/jszip.min.js | 15 -
docs/_style/prism-master/vendor/promise.js | 5 -
docs/_style/style.css | 81 -
docs/book/00-Introduction.md | 99 -
docs/book/00-On-Java-8.md | 64 -
docs/book/00-Preface.md | 100 -
docs/book/01-What-is-an-Object.md | 294 -
...2-Installing-Java-and-the-Book-Examples.md | 196 -
docs/book/03-Objects-Everywhere.md | 629 --
docs/book/04-Operators.md | 1471 -----
docs/book/05-Control-Flow.md | 827 ---
docs/book/06-Housekeeping.md | 1824 ------
docs/book/07-Implementation-Hiding.md | 694 ---
docs/book/08-Reuse.md | 1274 ----
docs/book/09-Polymorphism.md | 1257 ----
docs/book/10-Interfaces.md | 1820 ------
docs/book/11-Inner-Classes.md | 1450 -----
docs/book/12-Collections.md | 1755 ------
docs/book/13-Functional-Programming.md | 1524 -----
docs/book/14-Streams.md | 2153 -------
docs/book/15-Exceptions.md | 2199 -------
docs/book/16-Validating-Your-Code.md | 1961 -------
docs/book/17-Files.md | 854 ---
docs/book/18-Strings.md | 1544 -----
docs/book/19-Type-Information.md | 2494 --------
docs/book/20-Generics.md | 5192 -----------------
docs/book/21-Arrays.md | 2743 ---------
docs/book/22-Enumerations.md | 2111 -------
docs/book/23-Annotations.md | 1809 ------
docs/book/24-Concurrent-Programming.md | 3163 ----------
docs/book/25-Patterns.md | 1261 ----
docs/book/Appendix-Becoming-a-Programmer.md | 119 -
...efits-and-Costs-of-Static-Type-Checking.md | 29 -
docs/book/Appendix-Collection-Topics.md | 3236 ----------
docs/book/Appendix-Data-Compression.md | 252 -
docs/book/Appendix-IO-Streams.md | 547 --
docs/book/Appendix-Javadoc.md | 198 -
docs/book/Appendix-Low-Level-Concurrency.md | 1690 ------
docs/book/Appendix-New-IO.md | 1081 ----
docs/book/Appendix-Object-Serialization.md | 981 ----
.../Appendix-Passing-and-Returning-Objects.md | 58 -
docs/book/Appendix-Programming-Guidelines.md | 162 -
docs/book/Appendix-Standard-IO.md | 200 -
docs/book/Appendix-Supplements.md | 26 -
...Positive-Legacy-of-C-plus-plus-and-Java.md | 31 -
...endix-Understanding-equals-and-hashCode.md | 1015 ----
docs/book/GLOSSARY.md | 11 -
docs/favicon.ico | Bin 16958 -> 0 bytes
docs/images/1545758268350.png | Bin 20345 -> 0 bytes
docs/images/1545763399825.png | Bin 49793 -> 0 bytes
docs/images/1545764724202.png | Bin 50824 -> 0 bytes
docs/images/1545764780795.png | Bin 60425 -> 0 bytes
docs/images/1545764820176.png | Bin 53163 -> 0 bytes
docs/images/1545839316314.png | Bin 50495 -> 0 bytes
docs/images/1545841270997.png | Bin 41945 -> 0 bytes
docs/images/1554546258113.png | Bin 29644 -> 0 bytes
docs/images/1554546378822.png | Bin 13303 -> 0 bytes
docs/images/1554546452861.png | Bin 259226 -> 0 bytes
docs/images/1554546627710.png | Bin 6981 -> 0 bytes
docs/images/1554546666685.png | Bin 7891 -> 0 bytes
docs/images/1554546693664.png | Bin 7892 -> 0 bytes
docs/images/1554546847181.png | Bin 7891 -> 0 bytes
docs/images/1554546861836.png | Bin 7891 -> 0 bytes
docs/images/1554546881189.png | Bin 7884 -> 0 bytes
docs/images/1554546890132.png | Bin 7884 -> 0 bytes
docs/images/1561774164644.png | Bin 57171 -> 0 bytes
docs/images/1562204648023.png | Bin 56116 -> 0 bytes
docs/images/1562252767216.png | Bin 99346 -> 0 bytes
docs/images/1562406479787.png | Bin 49227 -> 0 bytes
docs/images/1562409366637.png | Bin 85411 -> 0 bytes
docs/images/1562409366638.png | Bin 30168 -> 0 bytes
docs/images/1562409926765.png | Bin 21837 -> 0 bytes
docs/images/1562653648586.png | Bin 33219 -> 0 bytes
docs/images/1562737974623.png | Bin 31295 -> 0 bytes
docs/images/1562999314238.png | Bin 164564 -> 0 bytes
docs/images/QQGroupQRCode.png | Bin 15366 -> 0 bytes
docs/images/collection.png | Bin 51285 -> 0 bytes
docs/images/cover.jpg | Bin 117331 -> 0 bytes
docs/images/cover_small.jpg | Bin 73325 -> 0 bytes
docs/images/designproxy.png | Bin 58606 -> 0 bytes
.../image-20190409114913825-4781754.png | Bin 38151 -> 0 bytes
docs/images/level_1_title.png | Bin 2530 -> 0 bytes
docs/images/level_2_title.png | Bin 14688 -> 0 bytes
docs/images/map.png | Bin 20386 -> 0 bytes
docs/images/qqgroup.png | Bin 2018 -> 0 bytes
docs/images/reader.png | Bin 45866 -> 0 bytes
docs/images/simple-collection-taxonomy.png | Bin 168908 -> 0 bytes
docs/index.html | 389 --
docs/sidebar.md | 448 --
1841 files changed, 5 insertions(+), 154409 deletions(-)
delete mode 100644 CONTRIBUTING.md
delete mode 100644 SUMMARY.md
delete mode 100644 book.json
delete mode 100644 cover.jpg
delete mode 100644 cover_small.jpg
delete mode 100644 docs/.nojekyll
delete mode 100644 docs/README.md
delete mode 100644 docs/_coverpage.md
delete mode 100644 docs/_style/prism-master/.editorconfig
delete mode 100644 docs/_style/prism-master/.gitattributes
delete mode 100644 docs/_style/prism-master/.gitignore
delete mode 100644 docs/_style/prism-master/.npmignore
delete mode 100644 docs/_style/prism-master/.travis.yml
delete mode 100644 docs/_style/prism-master/CHANGELOG.md
delete mode 100644 docs/_style/prism-master/CNAME
delete mode 100644 docs/_style/prism-master/LICENSE
delete mode 100644 docs/_style/prism-master/README.md
delete mode 100644 docs/_style/prism-master/bower.json
delete mode 100644 docs/_style/prism-master/code.js
delete mode 100644 docs/_style/prism-master/components.js
delete mode 100644 docs/_style/prism-master/components.json
delete mode 100644 docs/_style/prism-master/components/index.js
delete mode 100644 docs/_style/prism-master/components/prism-abap.js
delete mode 100644 docs/_style/prism-master/components/prism-abap.min.js
delete mode 100644 docs/_style/prism-master/components/prism-actionscript.js
delete mode 100644 docs/_style/prism-master/components/prism-actionscript.min.js
delete mode 100644 docs/_style/prism-master/components/prism-ada.js
delete mode 100644 docs/_style/prism-master/components/prism-ada.min.js
delete mode 100644 docs/_style/prism-master/components/prism-apacheconf.js
delete mode 100644 docs/_style/prism-master/components/prism-apacheconf.min.js
delete mode 100644 docs/_style/prism-master/components/prism-apl.js
delete mode 100644 docs/_style/prism-master/components/prism-apl.min.js
delete mode 100644 docs/_style/prism-master/components/prism-applescript.js
delete mode 100644 docs/_style/prism-master/components/prism-applescript.min.js
delete mode 100644 docs/_style/prism-master/components/prism-arduino.js
delete mode 100644 docs/_style/prism-master/components/prism-arduino.min.js
delete mode 100644 docs/_style/prism-master/components/prism-arff.js
delete mode 100644 docs/_style/prism-master/components/prism-arff.min.js
delete mode 100644 docs/_style/prism-master/components/prism-asciidoc.js
delete mode 100644 docs/_style/prism-master/components/prism-asciidoc.min.js
delete mode 100644 docs/_style/prism-master/components/prism-asm6502.js
delete mode 100644 docs/_style/prism-master/components/prism-asm6502.min.js
delete mode 100644 docs/_style/prism-master/components/prism-aspnet.js
delete mode 100644 docs/_style/prism-master/components/prism-aspnet.min.js
delete mode 100644 docs/_style/prism-master/components/prism-autohotkey.js
delete mode 100644 docs/_style/prism-master/components/prism-autohotkey.min.js
delete mode 100644 docs/_style/prism-master/components/prism-autoit.js
delete mode 100644 docs/_style/prism-master/components/prism-autoit.min.js
delete mode 100644 docs/_style/prism-master/components/prism-bash.js
delete mode 100644 docs/_style/prism-master/components/prism-bash.min.js
delete mode 100644 docs/_style/prism-master/components/prism-basic.js
delete mode 100644 docs/_style/prism-master/components/prism-basic.min.js
delete mode 100644 docs/_style/prism-master/components/prism-batch.js
delete mode 100644 docs/_style/prism-master/components/prism-batch.min.js
delete mode 100644 docs/_style/prism-master/components/prism-bison.js
delete mode 100644 docs/_style/prism-master/components/prism-bison.min.js
delete mode 100644 docs/_style/prism-master/components/prism-brainfuck.js
delete mode 100644 docs/_style/prism-master/components/prism-brainfuck.min.js
delete mode 100644 docs/_style/prism-master/components/prism-bro.js
delete mode 100644 docs/_style/prism-master/components/prism-bro.min.js
delete mode 100644 docs/_style/prism-master/components/prism-c.js
delete mode 100644 docs/_style/prism-master/components/prism-c.min.js
delete mode 100644 docs/_style/prism-master/components/prism-cil.js
delete mode 100644 docs/_style/prism-master/components/prism-cil.min.js
delete mode 100644 docs/_style/prism-master/components/prism-clike.js
delete mode 100644 docs/_style/prism-master/components/prism-clike.min.js
delete mode 100644 docs/_style/prism-master/components/prism-clojure.js
delete mode 100644 docs/_style/prism-master/components/prism-clojure.min.js
delete mode 100644 docs/_style/prism-master/components/prism-coffeescript.js
delete mode 100644 docs/_style/prism-master/components/prism-coffeescript.min.js
delete mode 100644 docs/_style/prism-master/components/prism-core.js
delete mode 100644 docs/_style/prism-master/components/prism-core.min.js
delete mode 100644 docs/_style/prism-master/components/prism-cpp.js
delete mode 100644 docs/_style/prism-master/components/prism-cpp.min.js
delete mode 100644 docs/_style/prism-master/components/prism-crystal.js
delete mode 100644 docs/_style/prism-master/components/prism-crystal.min.js
delete mode 100644 docs/_style/prism-master/components/prism-csharp.js
delete mode 100644 docs/_style/prism-master/components/prism-csharp.min.js
delete mode 100644 docs/_style/prism-master/components/prism-csp.js
delete mode 100644 docs/_style/prism-master/components/prism-csp.min.js
delete mode 100644 docs/_style/prism-master/components/prism-css-extras.js
delete mode 100644 docs/_style/prism-master/components/prism-css-extras.min.js
delete mode 100644 docs/_style/prism-master/components/prism-css.js
delete mode 100644 docs/_style/prism-master/components/prism-css.min.js
delete mode 100644 docs/_style/prism-master/components/prism-d.js
delete mode 100644 docs/_style/prism-master/components/prism-d.min.js
delete mode 100644 docs/_style/prism-master/components/prism-dart.js
delete mode 100644 docs/_style/prism-master/components/prism-dart.min.js
delete mode 100644 docs/_style/prism-master/components/prism-diff.js
delete mode 100644 docs/_style/prism-master/components/prism-diff.min.js
delete mode 100644 docs/_style/prism-master/components/prism-django.js
delete mode 100644 docs/_style/prism-master/components/prism-django.min.js
delete mode 100644 docs/_style/prism-master/components/prism-docker.js
delete mode 100644 docs/_style/prism-master/components/prism-docker.min.js
delete mode 100644 docs/_style/prism-master/components/prism-eiffel.js
delete mode 100644 docs/_style/prism-master/components/prism-eiffel.min.js
delete mode 100644 docs/_style/prism-master/components/prism-elixir.js
delete mode 100644 docs/_style/prism-master/components/prism-elixir.min.js
delete mode 100644 docs/_style/prism-master/components/prism-elm.js
delete mode 100644 docs/_style/prism-master/components/prism-elm.min.js
delete mode 100644 docs/_style/prism-master/components/prism-erb.js
delete mode 100644 docs/_style/prism-master/components/prism-erb.min.js
delete mode 100644 docs/_style/prism-master/components/prism-erlang.js
delete mode 100644 docs/_style/prism-master/components/prism-erlang.min.js
delete mode 100644 docs/_style/prism-master/components/prism-flow.js
delete mode 100644 docs/_style/prism-master/components/prism-flow.min.js
delete mode 100644 docs/_style/prism-master/components/prism-fortran.js
delete mode 100644 docs/_style/prism-master/components/prism-fortran.min.js
delete mode 100644 docs/_style/prism-master/components/prism-fsharp.js
delete mode 100644 docs/_style/prism-master/components/prism-fsharp.min.js
delete mode 100644 docs/_style/prism-master/components/prism-gcode.js
delete mode 100644 docs/_style/prism-master/components/prism-gcode.min.js
delete mode 100644 docs/_style/prism-master/components/prism-gedcom.js
delete mode 100644 docs/_style/prism-master/components/prism-gedcom.min.js
delete mode 100644 docs/_style/prism-master/components/prism-gherkin.js
delete mode 100644 docs/_style/prism-master/components/prism-gherkin.min.js
delete mode 100644 docs/_style/prism-master/components/prism-git.js
delete mode 100644 docs/_style/prism-master/components/prism-git.min.js
delete mode 100644 docs/_style/prism-master/components/prism-glsl.js
delete mode 100644 docs/_style/prism-master/components/prism-glsl.min.js
delete mode 100644 docs/_style/prism-master/components/prism-gml.js
delete mode 100644 docs/_style/prism-master/components/prism-gml.min.js
delete mode 100644 docs/_style/prism-master/components/prism-go.js
delete mode 100644 docs/_style/prism-master/components/prism-go.min.js
delete mode 100644 docs/_style/prism-master/components/prism-graphql.js
delete mode 100644 docs/_style/prism-master/components/prism-graphql.min.js
delete mode 100644 docs/_style/prism-master/components/prism-groovy.js
delete mode 100644 docs/_style/prism-master/components/prism-groovy.min.js
delete mode 100644 docs/_style/prism-master/components/prism-haml.js
delete mode 100644 docs/_style/prism-master/components/prism-haml.min.js
delete mode 100644 docs/_style/prism-master/components/prism-handlebars.js
delete mode 100644 docs/_style/prism-master/components/prism-handlebars.min.js
delete mode 100644 docs/_style/prism-master/components/prism-haskell.js
delete mode 100644 docs/_style/prism-master/components/prism-haskell.min.js
delete mode 100644 docs/_style/prism-master/components/prism-haxe.js
delete mode 100644 docs/_style/prism-master/components/prism-haxe.min.js
delete mode 100644 docs/_style/prism-master/components/prism-hpkp.js
delete mode 100644 docs/_style/prism-master/components/prism-hpkp.min.js
delete mode 100644 docs/_style/prism-master/components/prism-hsts.js
delete mode 100644 docs/_style/prism-master/components/prism-hsts.min.js
delete mode 100644 docs/_style/prism-master/components/prism-http.js
delete mode 100644 docs/_style/prism-master/components/prism-http.min.js
delete mode 100644 docs/_style/prism-master/components/prism-ichigojam.js
delete mode 100644 docs/_style/prism-master/components/prism-ichigojam.min.js
delete mode 100644 docs/_style/prism-master/components/prism-icon.js
delete mode 100644 docs/_style/prism-master/components/prism-icon.min.js
delete mode 100644 docs/_style/prism-master/components/prism-inform7.js
delete mode 100644 docs/_style/prism-master/components/prism-inform7.min.js
delete mode 100644 docs/_style/prism-master/components/prism-ini.js
delete mode 100644 docs/_style/prism-master/components/prism-ini.min.js
delete mode 100644 docs/_style/prism-master/components/prism-io.js
delete mode 100644 docs/_style/prism-master/components/prism-io.min.js
delete mode 100644 docs/_style/prism-master/components/prism-j.js
delete mode 100644 docs/_style/prism-master/components/prism-j.min.js
delete mode 100644 docs/_style/prism-master/components/prism-java.js
delete mode 100644 docs/_style/prism-master/components/prism-java.min.js
delete mode 100644 docs/_style/prism-master/components/prism-javascript.js
delete mode 100644 docs/_style/prism-master/components/prism-javascript.min.js
delete mode 100644 docs/_style/prism-master/components/prism-javastacktrace.js
delete mode 100644 docs/_style/prism-master/components/prism-javastacktrace.min.js
delete mode 100644 docs/_style/prism-master/components/prism-jolie.js
delete mode 100644 docs/_style/prism-master/components/prism-jolie.min.js
delete mode 100644 docs/_style/prism-master/components/prism-json.js
delete mode 100644 docs/_style/prism-master/components/prism-json.min.js
delete mode 100644 docs/_style/prism-master/components/prism-jsx.js
delete mode 100644 docs/_style/prism-master/components/prism-jsx.min.js
delete mode 100644 docs/_style/prism-master/components/prism-julia.js
delete mode 100644 docs/_style/prism-master/components/prism-julia.min.js
delete mode 100644 docs/_style/prism-master/components/prism-keyman.js
delete mode 100644 docs/_style/prism-master/components/prism-keyman.min.js
delete mode 100644 docs/_style/prism-master/components/prism-kotlin.js
delete mode 100644 docs/_style/prism-master/components/prism-kotlin.min.js
delete mode 100644 docs/_style/prism-master/components/prism-latex.js
delete mode 100644 docs/_style/prism-master/components/prism-latex.min.js
delete mode 100644 docs/_style/prism-master/components/prism-less.js
delete mode 100644 docs/_style/prism-master/components/prism-less.min.js
delete mode 100644 docs/_style/prism-master/components/prism-liquid.js
delete mode 100644 docs/_style/prism-master/components/prism-liquid.min.js
delete mode 100644 docs/_style/prism-master/components/prism-lisp.js
delete mode 100644 docs/_style/prism-master/components/prism-lisp.min.js
delete mode 100644 docs/_style/prism-master/components/prism-livescript.js
delete mode 100644 docs/_style/prism-master/components/prism-livescript.min.js
delete mode 100644 docs/_style/prism-master/components/prism-lolcode.js
delete mode 100644 docs/_style/prism-master/components/prism-lolcode.min.js
delete mode 100644 docs/_style/prism-master/components/prism-lua.js
delete mode 100644 docs/_style/prism-master/components/prism-lua.min.js
delete mode 100644 docs/_style/prism-master/components/prism-makefile.js
delete mode 100644 docs/_style/prism-master/components/prism-makefile.min.js
delete mode 100644 docs/_style/prism-master/components/prism-markdown.js
delete mode 100644 docs/_style/prism-master/components/prism-markdown.min.js
delete mode 100644 docs/_style/prism-master/components/prism-markup-templating.js
delete mode 100644 docs/_style/prism-master/components/prism-markup-templating.min.js
delete mode 100644 docs/_style/prism-master/components/prism-markup.js
delete mode 100644 docs/_style/prism-master/components/prism-markup.min.js
delete mode 100644 docs/_style/prism-master/components/prism-matlab.js
delete mode 100644 docs/_style/prism-master/components/prism-matlab.min.js
delete mode 100644 docs/_style/prism-master/components/prism-mel.js
delete mode 100644 docs/_style/prism-master/components/prism-mel.min.js
delete mode 100644 docs/_style/prism-master/components/prism-mizar.js
delete mode 100644 docs/_style/prism-master/components/prism-mizar.min.js
delete mode 100644 docs/_style/prism-master/components/prism-monkey.js
delete mode 100644 docs/_style/prism-master/components/prism-monkey.min.js
delete mode 100644 docs/_style/prism-master/components/prism-n4js.js
delete mode 100644 docs/_style/prism-master/components/prism-n4js.min.js
delete mode 100644 docs/_style/prism-master/components/prism-nasm.js
delete mode 100644 docs/_style/prism-master/components/prism-nasm.min.js
delete mode 100644 docs/_style/prism-master/components/prism-nginx.js
delete mode 100644 docs/_style/prism-master/components/prism-nginx.min.js
delete mode 100644 docs/_style/prism-master/components/prism-nim.js
delete mode 100644 docs/_style/prism-master/components/prism-nim.min.js
delete mode 100644 docs/_style/prism-master/components/prism-nix.js
delete mode 100644 docs/_style/prism-master/components/prism-nix.min.js
delete mode 100644 docs/_style/prism-master/components/prism-nsis.js
delete mode 100644 docs/_style/prism-master/components/prism-nsis.min.js
delete mode 100644 docs/_style/prism-master/components/prism-objectivec.js
delete mode 100644 docs/_style/prism-master/components/prism-objectivec.min.js
delete mode 100644 docs/_style/prism-master/components/prism-ocaml.js
delete mode 100644 docs/_style/prism-master/components/prism-ocaml.min.js
delete mode 100644 docs/_style/prism-master/components/prism-opencl.js
delete mode 100644 docs/_style/prism-master/components/prism-opencl.min.js
delete mode 100644 docs/_style/prism-master/components/prism-oz.js
delete mode 100644 docs/_style/prism-master/components/prism-oz.min.js
delete mode 100644 docs/_style/prism-master/components/prism-parigp.js
delete mode 100644 docs/_style/prism-master/components/prism-parigp.min.js
delete mode 100644 docs/_style/prism-master/components/prism-parser.js
delete mode 100644 docs/_style/prism-master/components/prism-parser.min.js
delete mode 100644 docs/_style/prism-master/components/prism-pascal.js
delete mode 100644 docs/_style/prism-master/components/prism-pascal.min.js
delete mode 100644 docs/_style/prism-master/components/prism-perl.js
delete mode 100644 docs/_style/prism-master/components/prism-perl.min.js
delete mode 100644 docs/_style/prism-master/components/prism-php-extras.js
delete mode 100644 docs/_style/prism-master/components/prism-php-extras.min.js
delete mode 100644 docs/_style/prism-master/components/prism-php.js
delete mode 100644 docs/_style/prism-master/components/prism-php.min.js
delete mode 100644 docs/_style/prism-master/components/prism-plsql.js
delete mode 100644 docs/_style/prism-master/components/prism-plsql.min.js
delete mode 100644 docs/_style/prism-master/components/prism-powershell.js
delete mode 100644 docs/_style/prism-master/components/prism-powershell.min.js
delete mode 100644 docs/_style/prism-master/components/prism-processing.js
delete mode 100644 docs/_style/prism-master/components/prism-processing.min.js
delete mode 100644 docs/_style/prism-master/components/prism-prolog.js
delete mode 100644 docs/_style/prism-master/components/prism-prolog.min.js
delete mode 100644 docs/_style/prism-master/components/prism-properties.js
delete mode 100644 docs/_style/prism-master/components/prism-properties.min.js
delete mode 100644 docs/_style/prism-master/components/prism-protobuf.js
delete mode 100644 docs/_style/prism-master/components/prism-protobuf.min.js
delete mode 100644 docs/_style/prism-master/components/prism-pug.js
delete mode 100644 docs/_style/prism-master/components/prism-pug.min.js
delete mode 100644 docs/_style/prism-master/components/prism-puppet.js
delete mode 100644 docs/_style/prism-master/components/prism-puppet.min.js
delete mode 100644 docs/_style/prism-master/components/prism-pure.js
delete mode 100644 docs/_style/prism-master/components/prism-pure.min.js
delete mode 100644 docs/_style/prism-master/components/prism-python.js
delete mode 100644 docs/_style/prism-master/components/prism-python.min.js
delete mode 100644 docs/_style/prism-master/components/prism-q.js
delete mode 100644 docs/_style/prism-master/components/prism-q.min.js
delete mode 100644 docs/_style/prism-master/components/prism-qore.js
delete mode 100644 docs/_style/prism-master/components/prism-qore.min.js
delete mode 100644 docs/_style/prism-master/components/prism-r.js
delete mode 100644 docs/_style/prism-master/components/prism-r.min.js
delete mode 100644 docs/_style/prism-master/components/prism-reason.js
delete mode 100644 docs/_style/prism-master/components/prism-reason.min.js
delete mode 100644 docs/_style/prism-master/components/prism-renpy.js
delete mode 100644 docs/_style/prism-master/components/prism-renpy.min.js
delete mode 100644 docs/_style/prism-master/components/prism-rest.js
delete mode 100644 docs/_style/prism-master/components/prism-rest.min.js
delete mode 100644 docs/_style/prism-master/components/prism-rip.js
delete mode 100644 docs/_style/prism-master/components/prism-rip.min.js
delete mode 100644 docs/_style/prism-master/components/prism-roboconf.js
delete mode 100644 docs/_style/prism-master/components/prism-roboconf.min.js
delete mode 100644 docs/_style/prism-master/components/prism-ruby.js
delete mode 100644 docs/_style/prism-master/components/prism-ruby.min.js
delete mode 100644 docs/_style/prism-master/components/prism-rust.js
delete mode 100644 docs/_style/prism-master/components/prism-rust.min.js
delete mode 100644 docs/_style/prism-master/components/prism-sas.js
delete mode 100644 docs/_style/prism-master/components/prism-sas.min.js
delete mode 100644 docs/_style/prism-master/components/prism-sass.js
delete mode 100644 docs/_style/prism-master/components/prism-sass.min.js
delete mode 100644 docs/_style/prism-master/components/prism-scala.js
delete mode 100644 docs/_style/prism-master/components/prism-scala.min.js
delete mode 100644 docs/_style/prism-master/components/prism-scheme.js
delete mode 100644 docs/_style/prism-master/components/prism-scheme.min.js
delete mode 100644 docs/_style/prism-master/components/prism-scss.js
delete mode 100644 docs/_style/prism-master/components/prism-scss.min.js
delete mode 100644 docs/_style/prism-master/components/prism-smalltalk.js
delete mode 100644 docs/_style/prism-master/components/prism-smalltalk.min.js
delete mode 100644 docs/_style/prism-master/components/prism-smarty.js
delete mode 100644 docs/_style/prism-master/components/prism-smarty.min.js
delete mode 100644 docs/_style/prism-master/components/prism-soy.js
delete mode 100644 docs/_style/prism-master/components/prism-soy.min.js
delete mode 100644 docs/_style/prism-master/components/prism-sql.js
delete mode 100644 docs/_style/prism-master/components/prism-sql.min.js
delete mode 100644 docs/_style/prism-master/components/prism-stylus.js
delete mode 100644 docs/_style/prism-master/components/prism-stylus.min.js
delete mode 100644 docs/_style/prism-master/components/prism-swift.js
delete mode 100644 docs/_style/prism-master/components/prism-swift.min.js
delete mode 100644 docs/_style/prism-master/components/prism-tap.js
delete mode 100644 docs/_style/prism-master/components/prism-tap.min.js
delete mode 100644 docs/_style/prism-master/components/prism-tcl.js
delete mode 100644 docs/_style/prism-master/components/prism-tcl.min.js
delete mode 100644 docs/_style/prism-master/components/prism-textile.js
delete mode 100644 docs/_style/prism-master/components/prism-textile.min.js
delete mode 100644 docs/_style/prism-master/components/prism-toml.js
delete mode 100644 docs/_style/prism-master/components/prism-toml.min.js
delete mode 100644 docs/_style/prism-master/components/prism-tsx.js
delete mode 100644 docs/_style/prism-master/components/prism-tsx.min.js
delete mode 100644 docs/_style/prism-master/components/prism-tt2.js
delete mode 100644 docs/_style/prism-master/components/prism-tt2.min.js
delete mode 100644 docs/_style/prism-master/components/prism-twig.js
delete mode 100644 docs/_style/prism-master/components/prism-twig.min.js
delete mode 100644 docs/_style/prism-master/components/prism-typescript.js
delete mode 100644 docs/_style/prism-master/components/prism-typescript.min.js
delete mode 100644 docs/_style/prism-master/components/prism-vala.js
delete mode 100644 docs/_style/prism-master/components/prism-vala.min.js
delete mode 100644 docs/_style/prism-master/components/prism-vbnet.js
delete mode 100644 docs/_style/prism-master/components/prism-vbnet.min.js
delete mode 100644 docs/_style/prism-master/components/prism-velocity.js
delete mode 100644 docs/_style/prism-master/components/prism-velocity.min.js
delete mode 100644 docs/_style/prism-master/components/prism-verilog.js
delete mode 100644 docs/_style/prism-master/components/prism-verilog.min.js
delete mode 100644 docs/_style/prism-master/components/prism-vhdl.js
delete mode 100644 docs/_style/prism-master/components/prism-vhdl.min.js
delete mode 100644 docs/_style/prism-master/components/prism-vim.js
delete mode 100644 docs/_style/prism-master/components/prism-vim.min.js
delete mode 100644 docs/_style/prism-master/components/prism-visual-basic.js
delete mode 100644 docs/_style/prism-master/components/prism-visual-basic.min.js
delete mode 100644 docs/_style/prism-master/components/prism-wasm.js
delete mode 100644 docs/_style/prism-master/components/prism-wasm.min.js
delete mode 100644 docs/_style/prism-master/components/prism-wiki.js
delete mode 100644 docs/_style/prism-master/components/prism-wiki.min.js
delete mode 100644 docs/_style/prism-master/components/prism-xeora.js
delete mode 100644 docs/_style/prism-master/components/prism-xeora.min.js
delete mode 100644 docs/_style/prism-master/components/prism-xojo.js
delete mode 100644 docs/_style/prism-master/components/prism-xojo.min.js
delete mode 100644 docs/_style/prism-master/components/prism-xquery.js
delete mode 100644 docs/_style/prism-master/components/prism-xquery.min.js
delete mode 100644 docs/_style/prism-master/components/prism-yaml.js
delete mode 100644 docs/_style/prism-master/components/prism-yaml.min.js
delete mode 100644 docs/_style/prism-master/composer.json
delete mode 100644 docs/_style/prism-master/download.html
delete mode 100644 docs/_style/prism-master/download.js
delete mode 100644 docs/_style/prism-master/examples.html
delete mode 100644 docs/_style/prism-master/examples.js
delete mode 100644 docs/_style/prism-master/examples/prism-abap.html
delete mode 100644 docs/_style/prism-master/examples/prism-actionscript.html
delete mode 100644 docs/_style/prism-master/examples/prism-ada.html
delete mode 100644 docs/_style/prism-master/examples/prism-apacheconf.html
delete mode 100644 docs/_style/prism-master/examples/prism-apl.html
delete mode 100644 docs/_style/prism-master/examples/prism-applescript.html
delete mode 100644 docs/_style/prism-master/examples/prism-arduino.html
delete mode 100644 docs/_style/prism-master/examples/prism-arff.html
delete mode 100644 docs/_style/prism-master/examples/prism-asciidoc.html
delete mode 100644 docs/_style/prism-master/examples/prism-asm6502.html
delete mode 100644 docs/_style/prism-master/examples/prism-aspnet.html
delete mode 100644 docs/_style/prism-master/examples/prism-autohotkey.html
delete mode 100644 docs/_style/prism-master/examples/prism-autoit.html
delete mode 100644 docs/_style/prism-master/examples/prism-bash.html
delete mode 100644 docs/_style/prism-master/examples/prism-basic.html
delete mode 100644 docs/_style/prism-master/examples/prism-batch.html
delete mode 100644 docs/_style/prism-master/examples/prism-bison.html
delete mode 100644 docs/_style/prism-master/examples/prism-brainfuck.html
delete mode 100644 docs/_style/prism-master/examples/prism-bro.html
delete mode 100644 docs/_style/prism-master/examples/prism-c.html
delete mode 100644 docs/_style/prism-master/examples/prism-clike.html
delete mode 100644 docs/_style/prism-master/examples/prism-clojure.html
delete mode 100644 docs/_style/prism-master/examples/prism-coffeescript.html
delete mode 100644 docs/_style/prism-master/examples/prism-cpp.html
delete mode 100644 docs/_style/prism-master/examples/prism-crystal.html
delete mode 100644 docs/_style/prism-master/examples/prism-csharp.html
delete mode 100644 docs/_style/prism-master/examples/prism-csp.html
delete mode 100644 docs/_style/prism-master/examples/prism-css.html
delete mode 100644 docs/_style/prism-master/examples/prism-d.html
delete mode 100644 docs/_style/prism-master/examples/prism-dart.html
delete mode 100644 docs/_style/prism-master/examples/prism-diff.html
delete mode 100644 docs/_style/prism-master/examples/prism-django.html
delete mode 100644 docs/_style/prism-master/examples/prism-docker.html
delete mode 100644 docs/_style/prism-master/examples/prism-eiffel.html
delete mode 100644 docs/_style/prism-master/examples/prism-elixir.html
delete mode 100644 docs/_style/prism-master/examples/prism-elm.html
delete mode 100644 docs/_style/prism-master/examples/prism-erb.html
delete mode 100644 docs/_style/prism-master/examples/prism-erlang.html
delete mode 100644 docs/_style/prism-master/examples/prism-flow.html
delete mode 100644 docs/_style/prism-master/examples/prism-fortran.html
delete mode 100644 docs/_style/prism-master/examples/prism-fsharp.html
delete mode 100644 docs/_style/prism-master/examples/prism-gcode.html
delete mode 100644 docs/_style/prism-master/examples/prism-gedcom.html
delete mode 100644 docs/_style/prism-master/examples/prism-gherkin.html
delete mode 100644 docs/_style/prism-master/examples/prism-git.html
delete mode 100644 docs/_style/prism-master/examples/prism-glsl.html
delete mode 100644 docs/_style/prism-master/examples/prism-gml.html
delete mode 100644 docs/_style/prism-master/examples/prism-go.html
delete mode 100644 docs/_style/prism-master/examples/prism-graphql.html
delete mode 100644 docs/_style/prism-master/examples/prism-groovy.html
delete mode 100644 docs/_style/prism-master/examples/prism-haml.html
delete mode 100644 docs/_style/prism-master/examples/prism-handlebars.html
delete mode 100644 docs/_style/prism-master/examples/prism-haskell.html
delete mode 100644 docs/_style/prism-master/examples/prism-haxe.html
delete mode 100644 docs/_style/prism-master/examples/prism-hpkp.html
delete mode 100644 docs/_style/prism-master/examples/prism-hsts.html
delete mode 100644 docs/_style/prism-master/examples/prism-http.html
delete mode 100644 docs/_style/prism-master/examples/prism-ichigojam.html
delete mode 100644 docs/_style/prism-master/examples/prism-icon.html
delete mode 100644 docs/_style/prism-master/examples/prism-inform7.html
delete mode 100644 docs/_style/prism-master/examples/prism-ini.html
delete mode 100644 docs/_style/prism-master/examples/prism-io.html
delete mode 100644 docs/_style/prism-master/examples/prism-j.html
delete mode 100644 docs/_style/prism-master/examples/prism-java.html
delete mode 100644 docs/_style/prism-master/examples/prism-javascript.html
delete mode 100644 docs/_style/prism-master/examples/prism-javastacktrace.html
delete mode 100644 docs/_style/prism-master/examples/prism-jolie.html
delete mode 100644 docs/_style/prism-master/examples/prism-jsx.html
delete mode 100644 docs/_style/prism-master/examples/prism-julia.html
delete mode 100644 docs/_style/prism-master/examples/prism-keyman.html
delete mode 100644 docs/_style/prism-master/examples/prism-kotlin.html
delete mode 100644 docs/_style/prism-master/examples/prism-latex.html
delete mode 100644 docs/_style/prism-master/examples/prism-less.html
delete mode 100644 docs/_style/prism-master/examples/prism-liquid.html
delete mode 100644 docs/_style/prism-master/examples/prism-lisp.html
delete mode 100644 docs/_style/prism-master/examples/prism-livescript.html
delete mode 100644 docs/_style/prism-master/examples/prism-lolcode.html
delete mode 100644 docs/_style/prism-master/examples/prism-lua.html
delete mode 100644 docs/_style/prism-master/examples/prism-makefile.html
delete mode 100644 docs/_style/prism-master/examples/prism-markdown.html
delete mode 100644 docs/_style/prism-master/examples/prism-markup.html
delete mode 100644 docs/_style/prism-master/examples/prism-matlab.html
delete mode 100644 docs/_style/prism-master/examples/prism-mel.html
delete mode 100644 docs/_style/prism-master/examples/prism-mizar.html
delete mode 100644 docs/_style/prism-master/examples/prism-monkey.html
delete mode 100644 docs/_style/prism-master/examples/prism-n4js.html
delete mode 100644 docs/_style/prism-master/examples/prism-nasm.html
delete mode 100644 docs/_style/prism-master/examples/prism-nginx.html
delete mode 100644 docs/_style/prism-master/examples/prism-nim.html
delete mode 100644 docs/_style/prism-master/examples/prism-nix.html
delete mode 100644 docs/_style/prism-master/examples/prism-nsis.html
delete mode 100644 docs/_style/prism-master/examples/prism-objectivec.html
delete mode 100644 docs/_style/prism-master/examples/prism-ocaml.html
delete mode 100644 docs/_style/prism-master/examples/prism-opencl.html
delete mode 100644 docs/_style/prism-master/examples/prism-oz.html
delete mode 100644 docs/_style/prism-master/examples/prism-parigp.html
delete mode 100644 docs/_style/prism-master/examples/prism-parser.html
delete mode 100644 docs/_style/prism-master/examples/prism-pascal.html
delete mode 100644 docs/_style/prism-master/examples/prism-perl.html
delete mode 100644 docs/_style/prism-master/examples/prism-php.html
delete mode 100644 docs/_style/prism-master/examples/prism-plsql.html
delete mode 100644 docs/_style/prism-master/examples/prism-powershell.html
delete mode 100644 docs/_style/prism-master/examples/prism-processing.html
delete mode 100644 docs/_style/prism-master/examples/prism-prolog.html
delete mode 100644 docs/_style/prism-master/examples/prism-properties.html
delete mode 100644 docs/_style/prism-master/examples/prism-pug.html
delete mode 100644 docs/_style/prism-master/examples/prism-puppet.html
delete mode 100644 docs/_style/prism-master/examples/prism-pure.html
delete mode 100644 docs/_style/prism-master/examples/prism-python.html
delete mode 100644 docs/_style/prism-master/examples/prism-q.html
delete mode 100644 docs/_style/prism-master/examples/prism-qore.html
delete mode 100644 docs/_style/prism-master/examples/prism-r.html
delete mode 100644 docs/_style/prism-master/examples/prism-reason.html
delete mode 100644 docs/_style/prism-master/examples/prism-renpy.html
delete mode 100644 docs/_style/prism-master/examples/prism-rest.html
delete mode 100644 docs/_style/prism-master/examples/prism-rip.html
delete mode 100644 docs/_style/prism-master/examples/prism-roboconf.html
delete mode 100644 docs/_style/prism-master/examples/prism-ruby.html
delete mode 100644 docs/_style/prism-master/examples/prism-rust.html
delete mode 100644 docs/_style/prism-master/examples/prism-sas.html
delete mode 100644 docs/_style/prism-master/examples/prism-sass.html
delete mode 100644 docs/_style/prism-master/examples/prism-scala.html
delete mode 100644 docs/_style/prism-master/examples/prism-scheme.html
delete mode 100644 docs/_style/prism-master/examples/prism-scss.html
delete mode 100644 docs/_style/prism-master/examples/prism-smalltalk.html
delete mode 100644 docs/_style/prism-master/examples/prism-smarty.html
delete mode 100644 docs/_style/prism-master/examples/prism-soy.html
delete mode 100644 docs/_style/prism-master/examples/prism-sql.html
delete mode 100644 docs/_style/prism-master/examples/prism-stylus.html
delete mode 100644 docs/_style/prism-master/examples/prism-swift.html
delete mode 100644 docs/_style/prism-master/examples/prism-tcl.html
delete mode 100644 docs/_style/prism-master/examples/prism-textile.html
delete mode 100644 docs/_style/prism-master/examples/prism-tsx.html
delete mode 100644 docs/_style/prism-master/examples/prism-tt2.html
delete mode 100644 docs/_style/prism-master/examples/prism-twig.html
delete mode 100644 docs/_style/prism-master/examples/prism-typescript.html
delete mode 100644 docs/_style/prism-master/examples/prism-vala.html
delete mode 100644 docs/_style/prism-master/examples/prism-vbnet.html
delete mode 100644 docs/_style/prism-master/examples/prism-velocity.html
delete mode 100644 docs/_style/prism-master/examples/prism-verilog.html
delete mode 100644 docs/_style/prism-master/examples/prism-vhdl.html
delete mode 100644 docs/_style/prism-master/examples/prism-vim.html
delete mode 100644 docs/_style/prism-master/examples/prism-visual-basic.html
delete mode 100644 docs/_style/prism-master/examples/prism-wasm.html
delete mode 100644 docs/_style/prism-master/examples/prism-wiki.html
delete mode 100644 docs/_style/prism-master/examples/prism-xeora.html
delete mode 100644 docs/_style/prism-master/examples/prism-xojo.html
delete mode 100644 docs/_style/prism-master/examples/prism-xquery.html
delete mode 100644 docs/_style/prism-master/examples/prism-yaml.html
delete mode 100644 docs/_style/prism-master/extending.html
delete mode 100644 docs/_style/prism-master/faq.html
delete mode 100644 docs/_style/prism-master/favicon.png
delete mode 100644 docs/_style/prism-master/gulpfile.js
delete mode 100644 docs/_style/prism-master/img/logo-ala.png
delete mode 100644 docs/_style/prism-master/img/logo-css-tricks.png
delete mode 100644 docs/_style/prism-master/img/logo-drupal.png
delete mode 100644 docs/_style/prism-master/img/logo-mdn.png
delete mode 100644 docs/_style/prism-master/img/logo-react.png
delete mode 100644 docs/_style/prism-master/img/logo-sitepoint.png
delete mode 100644 docs/_style/prism-master/img/logo-smashing.png
delete mode 100644 docs/_style/prism-master/img/logo-stripe.png
delete mode 100644 docs/_style/prism-master/img/spectrum.png
delete mode 100644 docs/_style/prism-master/index.html
delete mode 100644 docs/_style/prism-master/logo.svg
delete mode 100644 docs/_style/prism-master/package.json
delete mode 100644 docs/_style/prism-master/plugins/autolinker/index.html
delete mode 100644 docs/_style/prism-master/plugins/autolinker/prism-autolinker.css
delete mode 100644 docs/_style/prism-master/plugins/autolinker/prism-autolinker.js
delete mode 100644 docs/_style/prism-master/plugins/autolinker/prism-autolinker.min.js
delete mode 100644 docs/_style/prism-master/plugins/autoloader/index.html
delete mode 100644 docs/_style/prism-master/plugins/autoloader/prism-autoloader.js
delete mode 100644 docs/_style/prism-master/plugins/autoloader/prism-autoloader.min.js
delete mode 100644 docs/_style/prism-master/plugins/command-line/index.html
delete mode 100644 docs/_style/prism-master/plugins/command-line/prism-command-line.css
delete mode 100644 docs/_style/prism-master/plugins/command-line/prism-command-line.js
delete mode 100644 docs/_style/prism-master/plugins/command-line/prism-command-line.min.js
delete mode 100644 docs/_style/prism-master/plugins/copy-to-clipboard/index.html
delete mode 100644 docs/_style/prism-master/plugins/copy-to-clipboard/prism-copy-to-clipboard.js
delete mode 100644 docs/_style/prism-master/plugins/copy-to-clipboard/prism-copy-to-clipboard.min.js
delete mode 100644 docs/_style/prism-master/plugins/custom-class/index.html
delete mode 100644 docs/_style/prism-master/plugins/custom-class/prism-custom-class.js
delete mode 100644 docs/_style/prism-master/plugins/custom-class/prism-custom-class.min.js
delete mode 100644 docs/_style/prism-master/plugins/data-uri-highlight/index.html
delete mode 100644 docs/_style/prism-master/plugins/data-uri-highlight/prism-data-uri-highlight.js
delete mode 100644 docs/_style/prism-master/plugins/data-uri-highlight/prism-data-uri-highlight.min.js
delete mode 100644 docs/_style/prism-master/plugins/file-highlight/index.html
delete mode 100644 docs/_style/prism-master/plugins/file-highlight/prism-file-highlight.js
delete mode 100644 docs/_style/prism-master/plugins/file-highlight/prism-file-highlight.min.js
delete mode 100644 docs/_style/prism-master/plugins/highlight-keywords/index.html
delete mode 100644 docs/_style/prism-master/plugins/highlight-keywords/prism-highlight-keywords.js
delete mode 100644 docs/_style/prism-master/plugins/highlight-keywords/prism-highlight-keywords.min.js
delete mode 100644 docs/_style/prism-master/plugins/index.html
delete mode 100644 docs/_style/prism-master/plugins/jsonp-highlight/index.html
delete mode 100644 docs/_style/prism-master/plugins/jsonp-highlight/prism-jsonp-highlight.js
delete mode 100644 docs/_style/prism-master/plugins/jsonp-highlight/prism-jsonp-highlight.min.js
delete mode 100644 docs/_style/prism-master/plugins/keep-markup/index.html
delete mode 100644 docs/_style/prism-master/plugins/keep-markup/prism-keep-markup.js
delete mode 100644 docs/_style/prism-master/plugins/keep-markup/prism-keep-markup.min.js
delete mode 100644 docs/_style/prism-master/plugins/line-highlight/index.html
delete mode 100644 docs/_style/prism-master/plugins/line-highlight/prism-line-highlight.css
delete mode 100644 docs/_style/prism-master/plugins/line-highlight/prism-line-highlight.js
delete mode 100644 docs/_style/prism-master/plugins/line-highlight/prism-line-highlight.min.js
delete mode 100644 docs/_style/prism-master/plugins/line-numbers/index.html
delete mode 100644 docs/_style/prism-master/plugins/line-numbers/prism-line-numbers.css
delete mode 100644 docs/_style/prism-master/plugins/line-numbers/prism-line-numbers.js
delete mode 100644 docs/_style/prism-master/plugins/line-numbers/prism-line-numbers.min.js
delete mode 100644 docs/_style/prism-master/plugins/normalize-whitespace/demo.html
delete mode 100644 docs/_style/prism-master/plugins/normalize-whitespace/index.html
delete mode 100644 docs/_style/prism-master/plugins/normalize-whitespace/prism-normalize-whitespace.js
delete mode 100644 docs/_style/prism-master/plugins/normalize-whitespace/prism-normalize-whitespace.min.js
delete mode 100644 docs/_style/prism-master/plugins/previewers/index.html
delete mode 100644 docs/_style/prism-master/plugins/previewers/prism-previewers.css
delete mode 100644 docs/_style/prism-master/plugins/previewers/prism-previewers.js
delete mode 100644 docs/_style/prism-master/plugins/previewers/prism-previewers.min.js
delete mode 100644 docs/_style/prism-master/plugins/remove-initial-line-feed/index.html
delete mode 100644 docs/_style/prism-master/plugins/remove-initial-line-feed/prism-remove-initial-line-feed.js
delete mode 100644 docs/_style/prism-master/plugins/remove-initial-line-feed/prism-remove-initial-line-feed.min.js
delete mode 100644 docs/_style/prism-master/plugins/show-invisibles/index.html
delete mode 100644 docs/_style/prism-master/plugins/show-invisibles/prism-show-invisibles.css
delete mode 100644 docs/_style/prism-master/plugins/show-invisibles/prism-show-invisibles.js
delete mode 100644 docs/_style/prism-master/plugins/show-invisibles/prism-show-invisibles.min.js
delete mode 100644 docs/_style/prism-master/plugins/show-language/index.html
delete mode 100644 docs/_style/prism-master/plugins/show-language/prism-show-language.js
delete mode 100644 docs/_style/prism-master/plugins/show-language/prism-show-language.min.js
delete mode 100644 docs/_style/prism-master/plugins/toolbar/index.html
delete mode 100644 docs/_style/prism-master/plugins/toolbar/prism-toolbar.css
delete mode 100644 docs/_style/prism-master/plugins/toolbar/prism-toolbar.js
delete mode 100644 docs/_style/prism-master/plugins/toolbar/prism-toolbar.min.js
delete mode 100644 docs/_style/prism-master/plugins/unescaped-markup/index.html
delete mode 100644 docs/_style/prism-master/plugins/unescaped-markup/prism-unescaped-markup.css
delete mode 100644 docs/_style/prism-master/plugins/unescaped-markup/prism-unescaped-markup.js
delete mode 100644 docs/_style/prism-master/plugins/unescaped-markup/prism-unescaped-markup.min.js
delete mode 100644 docs/_style/prism-master/plugins/wpd/index.html
delete mode 100644 docs/_style/prism-master/plugins/wpd/prism-wpd.css
delete mode 100644 docs/_style/prism-master/plugins/wpd/prism-wpd.js
delete mode 100644 docs/_style/prism-master/plugins/wpd/prism-wpd.min.js
delete mode 100644 docs/_style/prism-master/prefixfree.min.js
delete mode 100644 docs/_style/prism-master/prism.js
delete mode 100644 docs/_style/prism-master/style.css
delete mode 100644 docs/_style/prism-master/templates/footer.html
delete mode 100644 docs/_style/prism-master/templates/header-download.html
delete mode 100644 docs/_style/prism-master/templates/header-main.html
delete mode 100644 docs/_style/prism-master/templates/header-plugins.html
delete mode 100644 docs/_style/prism-master/test-suite.html
delete mode 100644 docs/_style/prism-master/test.html
delete mode 100644 docs/_style/prism-master/tests/helper/prism-loader.js
delete mode 100644 docs/_style/prism-master/tests/helper/test-case.js
delete mode 100644 docs/_style/prism-master/tests/helper/test-discovery.js
delete mode 100644 docs/_style/prism-master/tests/helper/token-stream-transformer.js
delete mode 100644 docs/_style/prism-master/tests/languages/abap/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/abap/eol-comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/abap/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/abap/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/abap/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/abap/string-template_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/abap/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/actionscript/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/actionscript/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ada/attr-name_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ada/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ada/char_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ada/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ada/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ada/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ada/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ada/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ada/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/apacheconf/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/apacheconf/directive-block_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/apacheconf/directive-flags_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/apacheconf/directive-inline_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/apacheconf/regex_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/apacheconf/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/apacheconf/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/apl/assignment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/apl/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/apl/constant_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/apl/dfn_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/apl/dyadic-operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/apl/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/apl/monadic-operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/apl/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/apl/statement_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/apl/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/apl/system-function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/applescript/class_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/applescript/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/applescript/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/applescript/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/applescript/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/applescript/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/arff/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/arff/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/arff/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/arff/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/asciidoc/admonition_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/asciidoc/attribute-entry_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/asciidoc/attributes_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/asciidoc/callout_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/asciidoc/comment-block_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/asciidoc/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/asciidoc/entity_feature.js
delete mode 100644 docs/_style/prism-master/tests/languages/asciidoc/entity_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/asciidoc/hr_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/asciidoc/indented-block_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/asciidoc/inline_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/asciidoc/line-continuation_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/asciidoc/list-label_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/asciidoc/list-punctuation_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/asciidoc/literal-block_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/asciidoc/macro_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/asciidoc/other-block_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/asciidoc/page-break_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/asciidoc/passthrough-block_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/asciidoc/replacement_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/asciidoc/table_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/asciidoc/title_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/asm6502/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/asm6502/directive_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/asm6502/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/asm6502/opcode_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/asm6502/register_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/asm6502/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/aspnet/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/aspnet/page-directive_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/autohotkey/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/autohotkey/builtin_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/autohotkey/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/autohotkey/constant_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/autohotkey/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/autohotkey/important_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/autohotkey/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/autohotkey/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/autohotkey/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/autohotkey/selector_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/autohotkey/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/autohotkey/symbol_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/autohotkey/tag_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/autohotkey/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/autoit/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/autoit/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/autoit/directive_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/autoit/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/autoit/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/autoit/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/autoit/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/autoit/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/autoit/url_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/autoit/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/bash/arithmetic_environment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/bash/command_substitution_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/bash/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/bash/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/bash/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/bash/shebang_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/bash/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/bash/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/basic/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/basic/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/basic/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/basic/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/basic/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/basic/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/batch/command_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/batch/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/batch/label_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/bison/c_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/bison/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/bison/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/bison/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/bison/property_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/bison/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/brainfuck/all_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/bro/builtin_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/bro/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/bro/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/bro/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/bro/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/bro/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/c+pure/c_inclusion.test
delete mode 100644 docs/_style/prism-master/tests/languages/c/constant_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/c/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/c/macro_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/c/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/c/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/cil/asm_reference.test
delete mode 100644 docs/_style/prism-master/tests/languages/cil/boolean.test
delete mode 100644 docs/_style/prism-master/tests/languages/cil/comment.test
delete mode 100644 docs/_style/prism-master/tests/languages/cil/instructions.test
delete mode 100644 docs/_style/prism-master/tests/languages/cil/keywords.test
delete mode 100644 docs/_style/prism-master/tests/languages/cil/strings.test
delete mode 100644 docs/_style/prism-master/tests/languages/clike/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/clike/class-name_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/clike/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/clike/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/clike/issue1340.test
delete mode 100644 docs/_style/prism-master/tests/languages/clike/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/clike/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/clike/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/clike/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/clojure/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/clojure/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/clojure/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/clojure/operator_and_punctuation.test
delete mode 100644 docs/_style/prism-master/tests/languages/clojure/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/coffeescript+haml/coffeescript_inclusion.test
delete mode 100644 docs/_style/prism-master/tests/languages/coffeescript+pug/coffeescript_inclusion.test
delete mode 100644 docs/_style/prism-master/tests/languages/coffeescript/block-regex_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/coffeescript/class-member_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/coffeescript/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/coffeescript/inline-javascript_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/coffeescript/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/coffeescript/property_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/coffeescript/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/cpp+pure/cpp_inclusion.test
delete mode 100644 docs/_style/prism-master/tests/languages/cpp/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/cpp/class-name_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/cpp/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/cpp/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/cpp/raw_string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/crystal/attribute_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/crystal/expansion_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/crystal/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/crystal/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/csharp+aspnet/directive_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/csharp/class-name_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/csharp/generic_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/csharp/issue1091.test
delete mode 100644 docs/_style/prism-master/tests/languages/csharp/issue1365.test
delete mode 100644 docs/_style/prism-master/tests/languages/csharp/issue1371.test
delete mode 100644 docs/_style/prism-master/tests/languages/csharp/issue806.test
delete mode 100644 docs/_style/prism-master/tests/languages/csharp/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/csharp/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/csharp/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/csharp/preprocessor_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/csharp/punctuation_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/csharp/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/csp/directive_no_value_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/csp/directive_with_source_expression_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/csp/safe_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/csp/unsafe_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/css!+css-extras/entity_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/css!+css-extras/hexcode_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/css!+css-extras/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/css!+css-extras/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/css!+css-extras/selector_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/css!+css-extras/unit_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/css!+css-extras/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/css+haml/css+haml_usage.test
delete mode 100644 docs/_style/prism-master/tests/languages/css+http/css_inclusion.test
delete mode 100644 docs/_style/prism-master/tests/languages/css+textile/css_inclusion.test
delete mode 100644 docs/_style/prism-master/tests/languages/css/atrule_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/css/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/css/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/css/important_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/css/property_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/css/selector_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/css/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/css/url_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/d/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/d/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/d/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/d/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/d/property_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/d/register_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/d/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/d/token-string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/dart/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/dart/metadata_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/dart/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/dart/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/diff/coord_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/diff/diff_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/django/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/django/property_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/docker/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/docker/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/docker/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/eiffel/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/eiffel/char_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/eiffel/class-name_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/eiffel/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/eiffel/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/eiffel/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/eiffel/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/eiffel/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/elixir/atom_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/elixir/attr-name_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/elixir/attribute_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/elixir/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/elixir/capture_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/elixir/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/elixir/issue1392.test
delete mode 100644 docs/_style/prism-master/tests/languages/elixir/issue775.test
delete mode 100644 docs/_style/prism-master/tests/languages/elixir/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/elixir/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/elixir/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/elixir/regex_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/elixir/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/elm/builtin_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/elm/char_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/elm/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/elm/constant_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/elm/hvariable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/elm/import_statement_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/elm/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/elm/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/elm/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/elm/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/erb/erb_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/erb/erb_in_markup_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/erlang/atom_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/erlang/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/erlang/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/erlang/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/erlang/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/erlang/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/erlang/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/erlang/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/erlang/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/flow/flow-punctuation_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/flow/function-variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/flow/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/flow/type_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/fortran+pure/fortran_inclusion.test
delete mode 100644 docs/_style/prism-master/tests/languages/fortran/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/fortran/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/fortran/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/fortran/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/fortran/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/fortran/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/fsharp/annotation_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/fsharp/class-name_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/fsharp/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/fsharp/computation-expression_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/fsharp/issue1480.test
delete mode 100644 docs/_style/prism-master/tests/languages/fsharp/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/fsharp/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/fsharp/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/fsharp/preprocessor_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/fsharp/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/gcode/checksum_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/gcode/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/gcode/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/gcode/property_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/gcode/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/gedcom/level_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/gedcom/line-value_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/gedcom/pointer_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/gedcom/tag_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/gherkin/atrule_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/gherkin/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/gherkin/feature_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/gherkin/outline_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/gherkin/pystring_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/gherkin/scenario_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/gherkin/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/gherkin/table_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/gherkin/tag_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/git/command_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/git/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/git/commit_sha1_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/git/coord_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/git/diff_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/git/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/glsl/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/glsl/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/glsl/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/glsl/preprocessor_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/go/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/go/builtin_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/go/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/go/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/go/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/go/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/graphql/attr-name_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/graphql/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/graphql/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/graphql/directive_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/graphql/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/graphql/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/graphql/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/graphql/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/groovy/annotation_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/groovy/issue1049.js
delete mode 100644 docs/_style/prism-master/tests/languages/groovy/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/groovy/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/groovy/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/groovy/shebang_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/groovy/spock-block_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/groovy/string-interpolation_feature.js
delete mode 100644 docs/_style/prism-master/tests/languages/groovy/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/haml/code_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/haml/doctype_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/haml/interpolation_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/haml/multiline-code_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/haml/multiline-comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/haml/tag_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/handlebars+pug/handlebars_inclusion.test
delete mode 100644 docs/_style/prism-master/tests/languages/handlebars/block_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/handlebars/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/handlebars/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/handlebars/handlebars_in_markup_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/handlebars/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/handlebars/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/haskell/builtin_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/haskell/char_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/haskell/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/haskell/constant_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/haskell/hvariable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/haskell/import_statement_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/haskell/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/haskell/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/haskell/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/haskell/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/haxe/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/haxe/metadata_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/haxe/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/haxe/preprocessor_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/haxe/regex_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/haxe/reification_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/haxe/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/hpkp/safe_maxage_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/hpkp/sha256_pin_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/hpkp/unsafe_maxage_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/hsts/include_subdomains_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/hsts/preload_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/hsts/safe_maxage_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/hsts/unsafe_maxage_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/http/header-name_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/http/request-line_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/http/response-status_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ichigojam/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ichigojam/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ichigojam/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ichigojam/label_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ichigojam/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ichigojam/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ichigojam/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/icon/builtin-keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/icon/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/icon/directive_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/icon/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/icon/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/icon/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/icon/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/icon/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/inform7/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/inform7/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/inform7/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/inform7/position_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/inform7/property_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/inform7/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/inform7/title_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/inform7/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/inform7/verb_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ini/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ini/key_value_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ini/selector_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/io/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/io/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/io/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/io/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/j/adverb_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/j/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/j/conjunction_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/j/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/j/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/j/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/j/verb_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/java/function_featrue.test
delete mode 100644 docs/_style/prism-master/tests/languages/java/generics_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/java/issue1351.test
delete mode 100644 docs/_style/prism-master/tests/languages/java/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/java/module_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/java/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/java/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/java/package_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/javascript+haml/javascript_inclusion.test
delete mode 100644 docs/_style/prism-master/tests/languages/javascript+http/javascript_inclusion.test
delete mode 100644 docs/_style/prism-master/tests/languages/javascript/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/javascript/class-method_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/javascript/constant_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/javascript/function-variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/javascript/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/javascript/issue1337.test
delete mode 100644 docs/_style/prism-master/tests/languages/javascript/issue1340.test
delete mode 100644 docs/_style/prism-master/tests/languages/javascript/issue1397.test
delete mode 100644 docs/_style/prism-master/tests/languages/javascript/issue1526.test
delete mode 100644 docs/_style/prism-master/tests/languages/javascript/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/javascript/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/javascript/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/javascript/regex_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/javascript/supposed-classes_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/javascript/supposed-function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/javascript/template-string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/javascript/try-catch_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/javastacktrace/more_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/javastacktrace/stack-frame_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/javastacktrace/summary_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/jolie/deployment_features.test
delete mode 100644 docs/_style/prism-master/tests/languages/jolie/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/jolie/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/jolie/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/json+http/json-suffix_inclusion.test
delete mode 100644 docs/_style/prism-master/tests/languages/json+http/json_inclusion.test
delete mode 100644 docs/_style/prism-master/tests/languages/json/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/json/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/json/null_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/json/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/json/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/json/property_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/json/punctuation_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/json/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/jsx/issue1103.test
delete mode 100644 docs/_style/prism-master/tests/languages/jsx/issue1235.test
delete mode 100644 docs/_style/prism-master/tests/languages/jsx/issue1236.test
delete mode 100644 docs/_style/prism-master/tests/languages/jsx/issue1294.test
delete mode 100644 docs/_style/prism-master/tests/languages/jsx/issue1335.test
delete mode 100644 docs/_style/prism-master/tests/languages/jsx/issue1342.test
delete mode 100644 docs/_style/prism-master/tests/languages/jsx/issue1356.test
delete mode 100644 docs/_style/prism-master/tests/languages/jsx/issue1364.test
delete mode 100644 docs/_style/prism-master/tests/languages/jsx/issue1408.test
delete mode 100644 docs/_style/prism-master/tests/languages/jsx/issue1421.test
delete mode 100644 docs/_style/prism-master/tests/languages/jsx/plain-text_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/jsx/tag_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/julia/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/julia/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/julia/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/julia/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/julia/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/julia/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/keyman/atrule_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/keyman/bold_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/keyman/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/keyman/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/keyman/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/keyman/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/keyman/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/keyman/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/keyman/tag_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/kotlin/annotation_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/kotlin/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/kotlin/interpolation_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/kotlin/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/kotlin/label_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/kotlin/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/kotlin/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/kotlin/raw-string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/latex/cdata_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/latex/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/latex/equation_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/latex/headline_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/latex/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/latex/url_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/less+haml/less_inclusion.test
delete mode 100644 docs/_style/prism-master/tests/languages/less+pug/less_inclusion.test
delete mode 100644 docs/_style/prism-master/tests/languages/less/atrule_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/less/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/less/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/less/property_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/less/selector_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/liquid/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/liquid/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/liquid/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/liquid/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/lisp/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/lisp/car_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/lisp/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/lisp/declare_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/lisp/defun_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/lisp/defvar_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/lisp/heading_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/lisp/interactive_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/lisp/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/lisp/lambda-feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/lisp/lisp-property_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/lisp/number_boolean.test
delete mode 100644 docs/_style/prism-master/tests/languages/lisp/punctuation_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/lisp/quoted-symbol_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/lisp/splice_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/lisp/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/livescript/argument_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/livescript/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/livescript/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/livescript/identifier_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/livescript/interpolated-string.test
delete mode 100644 docs/_style/prism-master/tests/languages/livescript/keyword-operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/livescript/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/livescript/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/livescript/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/livescript/regex_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/livescript/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/lolcode/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/lolcode/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/lolcode/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/lolcode/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/lolcode/label_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/lolcode/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/lolcode/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/lolcode/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/lolcode/symbol_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/lolcode/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/lua/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/lua/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/lua/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/lua/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/lua/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/lua/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/makefile/builtin_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/makefile/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/makefile/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/makefile/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/makefile/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/makefile/symbol_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/makefile/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/markdown+haml/markdown_inclusion.test
delete mode 100644 docs/_style/prism-master/tests/languages/markdown+pug/markdown_inclusion.test
delete mode 100644 docs/_style/prism-master/tests/languages/markdown/blockquote_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/markdown/bold_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/markdown/code_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/markdown/hr_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/markdown/italic_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/markdown/list_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/markdown/strike_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/markdown/title_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/markdown/url-reference_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/markdown/url_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/markup!+css+javascript/issue1240.test
delete mode 100644 docs/_style/prism-master/tests/languages/markup!+css/css_inclusion.test
delete mode 100644 docs/_style/prism-master/tests/languages/markup!+javascript/javascript_inclusion.test
delete mode 100644 docs/_style/prism-master/tests/languages/markup+actionscript/xml_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/markup+css+wiki/table-tag_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/markup+haml/markup_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/markup+http/html_inclusion.test
delete mode 100644 docs/_style/prism-master/tests/languages/markup+http/xml-suffix_inclusion.test
delete mode 100644 docs/_style/prism-master/tests/languages/markup+http/xml_inclusion.test
delete mode 100644 docs/_style/prism-master/tests/languages/markup+javascript+csharp+aspnet/script_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/markup+php/php_in_markup_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/markup+pug/markup_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/markup+tt2/tt2_in_markup_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/markup/cdata_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/markup/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/markup/doctype_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/markup/entity_feature.js
delete mode 100644 docs/_style/prism-master/tests/languages/markup/entity_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/markup/issue585.test
delete mode 100644 docs/_style/prism-master/tests/languages/markup/issue888.test
delete mode 100644 docs/_style/prism-master/tests/languages/markup/prolog_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/markup/tag_attribute_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/markup/tag_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/matlab/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/matlab/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/matlab/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/matlab/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/matlab/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/matlab/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/mel/code_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/mel/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/mel/flag_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/mel/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/mel/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/mel/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/mel/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/mel/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/mel/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/mizar/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/mizar/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/mizar/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/mizar/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/mizar/parameter_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/mizar/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/monkey/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/monkey/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/monkey/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/monkey/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/monkey/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/monkey/preprocessor_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/monkey/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/monkey/type-char_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/n4js/annotation_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/n4js/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/nasm/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/nasm/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/nasm/label_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/nasm/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/nasm/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/nasm/register_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/nasm/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/nginx/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/nginx/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/nginx/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/nim/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/nim/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/nim/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/nim/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/nim/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/nim/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/nix/antiquotation_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/nix/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/nix/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/nix/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/nix/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/nix/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/nix/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/nix/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/nix/url_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/nsis/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/nsis/constant_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/nsis/important_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/nsis/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/nsis/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/nsis/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/nsis/property_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/nsis/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/nsis/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/objectivec/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/objectivec/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/objectivec/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ocaml/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ocaml/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ocaml/directive_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ocaml/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ocaml/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ocaml/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ocaml/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ocaml/type_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/opencl+c/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/opencl+c/constant_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/opencl+c/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/opencl+c/type_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/opencl+cpp/type_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/opencl/constant_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/opencl/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/opencl/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/oz/atom_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/oz/attr-name_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/oz/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/oz/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/oz/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/oz/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/oz/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/oz/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/oz/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/parigp/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/parigp/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/parigp/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/parigp/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/parigp/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/parigp/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/parser/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/parser/escape_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/parser/expression_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/parser/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/parser/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/parser/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/parser/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/parser/parser-comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/parser/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/parser/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/pascal/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/pascal/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/pascal/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/pascal/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/pascal/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/perl/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/perl/filehandle_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/perl/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/perl/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/perl/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/perl/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/perl/regex_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/perl/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/perl/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/perl/vstring_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/php!+php-extras/global_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/php!+php-extras/scope_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/php!+php-extras/this_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/php/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/php/constant_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/php/delimiter_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/php/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/php/package_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/php/property_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/php/shell-comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/php/string-interpolation_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/php/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/php/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/plsql/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/plsql/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/plsql/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/powershell/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/powershell/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/powershell/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/powershell/issue1407.test
delete mode 100644 docs/_style/prism-master/tests/languages/powershell/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/powershell/namespace_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/powershell/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/powershell/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/powershell/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/processing/constant_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/processing/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/processing/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/processing/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/processing/type_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/prolog/builtin_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/prolog/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/prolog/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/prolog/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/prolog/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/prolog/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/prolog/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/properties/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/properties/key_value_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/protobuf/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/protobuf/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/pug/code_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/pug/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/pug/doctype_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/pug/flow-control_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/pug/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/pug/mixin_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/pug/multiline-plain-text_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/pug/multiline-script_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/pug/plain-text_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/pug/script_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/pug/tag_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/puppet/attr-name_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/puppet/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/puppet/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/puppet/datatype_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/puppet/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/puppet/heredoc_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/puppet/interpolation_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/puppet/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/puppet/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/puppet/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/puppet/regex_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/puppet/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/puppet/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/pure/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/pure/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/pure/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/pure/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/pure/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/pure/special_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/pure/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/python/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/python/builtin_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/python/class-name_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/python/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/python/decorator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/python/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/python/issue1355.test
delete mode 100644 docs/_style/prism-master/tests/languages/python/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/python/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/python/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/python/string-interpolation_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/python/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/python/triple-quoted-string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/q/adverb_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/q/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/q/datetime_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/q/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/q/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/q/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/q/symbol_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/q/verb_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/qore/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/qore/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/qore/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/qore/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/qore/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/qore/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/qore/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/qore/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/r/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/r/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/r/ellipsis_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/r/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/r/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/r/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/r/percent-operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/r/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/reason/character_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/reason/class-name_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/reason/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/reason/constructor_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/reason/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/reason/label_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/reason/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/reason/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rest/command-line-option_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rest/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rest/directive_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rest/doctest-block_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rest/field_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rest/hr_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rest/inline_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rest/link-target_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rest/link_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rest/list-bullet_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rest/literal-block_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rest/quoted-literal-block_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rest/substitution-def_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rest/table_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rest/title_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rip/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rip/builtin_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rip/character_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rip/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rip/date_time_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rip/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rip/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rip/reference_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rip/regex_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rip/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rip/symbol_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/roboconf/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/roboconf/component_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/roboconf/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/roboconf/optional_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/roboconf/property_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/roboconf/value_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/roboconf/wildcard_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ruby/builtin_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ruby/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ruby/constant_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ruby/issue1336.test
delete mode 100644 docs/_style/prism-master/tests/languages/ruby/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ruby/method_definition_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ruby/regex_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ruby/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ruby/symbol_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/ruby/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rust/attribute_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rust/char_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rust/closure-params_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rust/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rust/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rust/issue1339.test
delete mode 100644 docs/_style/prism-master/tests/languages/rust/issue1353.test
delete mode 100644 docs/_style/prism-master/tests/languages/rust/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rust/lifetime-annotation_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rust/macro-rules_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rust/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rust/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/rust/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/sas/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/sas/datalines_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/sas/datetime_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/sas/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/sas/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/sas/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/sas/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/sass/atrule-line_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/sass/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/sass/property-line_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/sass/selector_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/sass/variable-line_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/scala/builtin_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/scala/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/scala/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/scala/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/scala/symbol_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/scheme/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/scheme/builtin_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/scheme/character_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/scheme/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/scheme/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/scheme/issue1331.test
delete mode 100644 docs/_style/prism-master/tests/languages/scheme/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/scheme/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/scheme/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/scheme/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/scss+haml/scss_inclusion.test
delete mode 100644 docs/_style/prism-master/tests/languages/scss+pug/scss_inclusion.test
delete mode 100644 docs/_style/prism-master/tests/languages/scss/atrule_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/scss/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/scss/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/scss/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/scss/null_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/scss/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/scss/placeholder_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/scss/property_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/scss/selector_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/scss/statement_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/scss/url_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/scss/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/smalltalk/block-arguments_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/smalltalk/character_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/smalltalk/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/smalltalk/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/smalltalk/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/smalltalk/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/smalltalk/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/smalltalk/symbol_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/smalltalk/temporary-variables_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/smarty/attr-name_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/smarty/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/smarty/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/smarty/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/smarty/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/smarty/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/smarty/smarty_in_markup_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/smarty/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/smarty/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/soy/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/soy/command-arg.test
delete mode 100644 docs/_style/prism-master/tests/languages/soy/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/soy/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/soy/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/soy/literal_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/soy/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/soy/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/soy/parameter_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/soy/property_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/soy/soy_in_markup_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/soy/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/soy/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/sql/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/sql/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/sql/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/sql/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/sql/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/sql/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/sql/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/sql/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/stylus+pug/stylus_inclusion.test
delete mode 100644 docs/_style/prism-master/tests/languages/stylus/atrule-declaration_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/stylus/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/stylus/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/stylus/func_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/stylus/hexcode_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/stylus/important_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/stylus/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/stylus/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/stylus/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/stylus/property-declaration_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/stylus/selector_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/stylus/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/stylus/url_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/stylus/variable-declaration_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/swift/atrule_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/swift/builtin_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/swift/constant_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/swift/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/swift/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/swift/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/tap/bail_out_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/tap/directive_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/tap/pass_fail_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/tap/plan_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/tap/pragma_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/tap/version_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/tap/yamlish_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/tcl/builtin_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/tcl/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/tcl/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/tcl/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/tcl/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/tcl/scope_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/tcl/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/tcl/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/textile/acronym_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/textile/block-tag_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/textile/footnote_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/textile/image_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/textile/inline_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/textile/link-ref_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/textile/link_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/textile/list_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/textile/mark_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/textile/table_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/toml/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/toml/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/toml/date_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/toml/key_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/toml/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/toml/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/toml/table_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/tsx/tag_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/tt2/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/tt2/delimiter_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/tt2/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/tt2/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/tt2/string-interpolation_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/tt2/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/tt2/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/twig+pug/twig_inclusion.test
delete mode 100644 docs/_style/prism-master/tests/languages/twig/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/twig/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/twig/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/twig/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/twig/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/twig/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/typescript/builtin_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/typescript/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/vala/class-name_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/vala/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/vala/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/vala/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/vala/punctuation_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/vala/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/vbnet/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/vbnet/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/velocity/directive_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/velocity/unparsed_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/velocity/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/velocity/velocity-comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/verilog/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/verilog/constant_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/verilog/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/verilog/important_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/verilog/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/verilog/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/verilog/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/verilog/property_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/verilog/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/vhdl/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/vhdl/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/vhdl/constant_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/vhdl/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/vhdl/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/vhdl/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/vhdl/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/vhdl/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/vhdl/vhdl-vectors_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/vim/builtin_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/vim/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/vim/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/vim/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/vim/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/vim/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/vim/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/visual-basic/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/visual-basic/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/visual-basic/date_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/visual-basic/directive_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/visual-basic/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/visual-basic/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/visual-basic/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/visual-basic/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/wasm/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/wasm/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/wasm/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/wasm/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/wasm/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/wiki/block-comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/wiki/emphasis_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/wiki/heading_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/wiki/hr_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/wiki/nowiki_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/wiki/symbol_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/wiki/url_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/wiki/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/xeora/constant_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/xeora/directive-block-close_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/xeora/directive-block-open_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/xeora/directive-block-separator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/xeora/directive-inline_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/xeora/function-block_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/xeora/function-inline_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/xeora/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/xojo/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/xojo/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/xojo/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/xojo/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/xojo/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/xojo/symbol_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/xquery/axis_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/xquery/builtin_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/xquery/extension_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/xquery/function_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/xquery/keyword-operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/xquery/keyword_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/xquery/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/xquery/operator_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/xquery/plain-text_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/xquery/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/xquery/tag_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/xquery/variable_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/xquery/xquery-attribute_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/xquery/xquery-comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/xquery/xquery-element_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/yaml/boolean_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/yaml/comment_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/yaml/datetime_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/yaml/directive_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/yaml/important_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/yaml/key_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/yaml/null_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/yaml/number_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/yaml/scalar_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/yaml/string_feature.test
delete mode 100644 docs/_style/prism-master/tests/languages/yaml/tag_feature.test
delete mode 100644 docs/_style/prism-master/tests/run.js
delete mode 100644 docs/_style/prism-master/tests/testrunner-tests.js
delete mode 100644 docs/_style/prism-master/themes/prism-coy.css
delete mode 100644 docs/_style/prism-master/themes/prism-dark.css
delete mode 100644 docs/_style/prism-master/themes/prism-funky.css
delete mode 100644 docs/_style/prism-master/themes/prism-okaidia.css
delete mode 100644 docs/_style/prism-master/themes/prism-solarizedlight.css
delete mode 100644 docs/_style/prism-master/themes/prism-tomorrow.css
delete mode 100644 docs/_style/prism-master/themes/prism-twilight.css
delete mode 100644 docs/_style/prism-master/themes/prism.css
delete mode 100644 docs/_style/prism-master/utopia.js
delete mode 100644 docs/_style/prism-master/vendor/FileSaver.min.js
delete mode 100644 docs/_style/prism-master/vendor/jszip.min.js
delete mode 100644 docs/_style/prism-master/vendor/promise.js
delete mode 100644 docs/_style/style.css
delete mode 100644 docs/book/00-Introduction.md
delete mode 100644 docs/book/00-On-Java-8.md
delete mode 100644 docs/book/00-Preface.md
delete mode 100644 docs/book/01-What-is-an-Object.md
delete mode 100644 docs/book/02-Installing-Java-and-the-Book-Examples.md
delete mode 100644 docs/book/03-Objects-Everywhere.md
delete mode 100644 docs/book/04-Operators.md
delete mode 100755 docs/book/05-Control-Flow.md
delete mode 100644 docs/book/06-Housekeeping.md
delete mode 100644 docs/book/07-Implementation-Hiding.md
delete mode 100644 docs/book/08-Reuse.md
delete mode 100644 docs/book/09-Polymorphism.md
delete mode 100644 docs/book/10-Interfaces.md
delete mode 100755 docs/book/11-Inner-Classes.md
delete mode 100644 docs/book/12-Collections.md
delete mode 100644 docs/book/13-Functional-Programming.md
delete mode 100644 docs/book/14-Streams.md
delete mode 100644 docs/book/15-Exceptions.md
delete mode 100644 docs/book/16-Validating-Your-Code.md
delete mode 100644 docs/book/17-Files.md
delete mode 100755 docs/book/18-Strings.md
delete mode 100755 docs/book/19-Type-Information.md
delete mode 100644 docs/book/20-Generics.md
delete mode 100755 docs/book/21-Arrays.md
delete mode 100644 docs/book/22-Enumerations.md
delete mode 100644 docs/book/23-Annotations.md
delete mode 100755 docs/book/24-Concurrent-Programming.md
delete mode 100644 docs/book/25-Patterns.md
delete mode 100644 docs/book/Appendix-Becoming-a-Programmer.md
delete mode 100644 docs/book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md
delete mode 100644 docs/book/Appendix-Collection-Topics.md
delete mode 100644 docs/book/Appendix-Data-Compression.md
delete mode 100644 docs/book/Appendix-IO-Streams.md
delete mode 100644 docs/book/Appendix-Javadoc.md
delete mode 100644 docs/book/Appendix-Low-Level-Concurrency.md
delete mode 100644 docs/book/Appendix-New-IO.md
delete mode 100644 docs/book/Appendix-Object-Serialization.md
delete mode 100644 docs/book/Appendix-Passing-and-Returning-Objects.md
delete mode 100644 docs/book/Appendix-Programming-Guidelines.md
delete mode 100755 docs/book/Appendix-Standard-IO.md
delete mode 100644 docs/book/Appendix-Supplements.md
delete mode 100644 docs/book/Appendix-The-Positive-Legacy-of-C-plus-plus-and-Java.md
delete mode 100644 docs/book/Appendix-Understanding-equals-and-hashCode.md
delete mode 100644 docs/book/GLOSSARY.md
delete mode 100644 docs/favicon.ico
delete mode 100644 docs/images/1545758268350.png
delete mode 100644 docs/images/1545763399825.png
delete mode 100644 docs/images/1545764724202.png
delete mode 100644 docs/images/1545764780795.png
delete mode 100644 docs/images/1545764820176.png
delete mode 100644 docs/images/1545839316314.png
delete mode 100644 docs/images/1545841270997.png
delete mode 100644 docs/images/1554546258113.png
delete mode 100644 docs/images/1554546378822.png
delete mode 100644 docs/images/1554546452861.png
delete mode 100644 docs/images/1554546627710.png
delete mode 100644 docs/images/1554546666685.png
delete mode 100644 docs/images/1554546693664.png
delete mode 100644 docs/images/1554546847181.png
delete mode 100644 docs/images/1554546861836.png
delete mode 100644 docs/images/1554546881189.png
delete mode 100644 docs/images/1554546890132.png
delete mode 100644 docs/images/1561774164644.png
delete mode 100644 docs/images/1562204648023.png
delete mode 100644 docs/images/1562252767216.png
delete mode 100644 docs/images/1562406479787.png
delete mode 100644 docs/images/1562409366637.png
delete mode 100644 docs/images/1562409366638.png
delete mode 100644 docs/images/1562409926765.png
delete mode 100644 docs/images/1562653648586.png
delete mode 100644 docs/images/1562737974623.png
delete mode 100644 docs/images/1562999314238.png
delete mode 100644 docs/images/QQGroupQRCode.png
delete mode 100644 docs/images/collection.png
delete mode 100644 docs/images/cover.jpg
delete mode 100644 docs/images/cover_small.jpg
delete mode 100644 docs/images/designproxy.png
delete mode 100644 docs/images/image-20190409114913825-4781754.png
delete mode 100644 docs/images/level_1_title.png
delete mode 100644 docs/images/level_2_title.png
delete mode 100644 docs/images/map.png
delete mode 100644 docs/images/qqgroup.png
delete mode 100644 docs/images/reader.png
delete mode 100644 docs/images/simple-collection-taxonomy.png
delete mode 100755 docs/index.html
delete mode 100644 docs/sidebar.md
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
deleted file mode 100644
index 907a705a..00000000
--- a/CONTRIBUTING.md
+++ /dev/null
@@ -1,45 +0,0 @@
-## 如何贡献项目
-
-领取或创建新的 [Issue](https://github.com/lingcoder/OnJava8/issues),如 [issue 14](https://github.com/lingcoder/OnJava8/issues/14) ,在编辑栏的右侧添加自己为 `Assignee`。
-
-在 [GitHub](https://github.com/lingcoder/OnJava8/fork) 上 `fork` 项目到自己的仓库,你的如 `user_name/OnJava8`,然后 `clone` 到本地,并设置用户信息。
-
-```bash
-$ git clone git@github.com:user_name/OnJava8.git
-
-$ cd OnJava8
-```
-
-修改代码后提交,并推送到自己的仓库,注意修改提交消息为对应 Issue 号和描述。
-
-```bash
-# 更新内容
-
-$ git commit -a -s
-
-# 在提交对话框里添加类似如下内容 "Fix issue #14: 描述你的修改内容"
-
-$ git push
-```
-
-在 [GitHub](https://github.com/lingcoder/OnJava8/pulls) 上提交 `Pull Request`,添加标签,并邀请维护者进行 `Review`。
-
-定期使用源项目仓库内容同步更新自己仓库的内容。
-
-```bash
-$ git remote add upstream https://github.com/lingcoder/OnJava8
-
-$ git fetch upstream
-
-$ git rebase upstream/master
-
-$ git push -f origin master
-```
-
-## 视频演示教程
-
-- https://www.bilibili.com/video/av58040840
-
-## 排版规范
-
-本开源书籍排版布局和翻译风格上参考**阮一峰**老师的 [中文技术文档的写作规范](https://github.com/ruanyf/document-style-guide)
diff --git a/README.md b/README.md
index 9e9e83bd..576a7651 100644
--- a/README.md
+++ b/README.md
@@ -1,62 +1,12 @@
# 《On Java 8》中文版
-## 书籍简介
+## 通知公告
-- 本书原作者为 [美] Bruce Eckel,即《Java 编程思想》的作者。
+图灵要出On Java 8的中文版了!
+非常感谢大家长久以来对本项目的支持和贡献,出于对原作者的敬意和对版权尊重,本项目将于2021年2月26日起闭源。
+之后,我将作为On Java 8的特邀审读嘉宾,继续贡献自己的一份力量!
-
-## 传送门
-
-- 目录阅读:[进入](https://github.com/LingCoder/OnJava8/blob/master/SUMMARY.md)
-
-- GitHub Pages 完整阅读:[进入](https://lingcoder.github.io/OnJava8/)
-
-- Gitee Pages 完整阅读:[进入](https://lingcoder.gitee.io/onjava8/)
-
-## 翻译进度
-
-- [x] [前言](docs/book/00-Preface.md)
-- [x] [简介](docs/book/00-Introduction.md)
-- [x] [第一章 对象的概念](docs/book/01-What-is-an-Object.md)
-- [x] [第二章 安装 Java 和本书用例](docs/book/02-Installing-Java-and-the-Book-Examples.md)
-- [x] [第三章 万物皆对象](docs/book/03-Objects-Everywhere.md)
-- [x] [第四章 运算符](docs/book/04-Operators.md)
-- [x] [第五章 控制流](docs/book/05-Control-Flow.md)
-- [x] [第六章 初始化和清理](docs/book/06-Housekeeping.md)
-- [x] [第七章 封装](docs/book/07-Implementation-Hiding.md)
-- [x] [第八章 复用](docs/book/08-Reuse.md)
-- [x] [第九章 多态](docs/book/09-Polymorphism.md)
-- [x] [第十章 接口](docs/book/10-Interfaces.md)
-- [x] [第十一章 内部类](docs/book/11-Inner-Classes.md)
-- [x] [第十二章 集合](docs/book/12-Collections.md)
-- [x] [第十三章 函数式编程](docs/book/13-Functional-Programming.md)
-- [x] [第十四章 流式编程](docs/book/14-Streams.md)
-- [x] [第十五章 异常](docs/book/15-Exceptions.md)
-- [x] [第十六章 代码校验](docs/book/16-Validating-Your-Code.md)
-- [x] [第十七章 文件](docs/book/17-Files.md)
-- [x] [第十八章 字符串](docs/book/18-Strings.md)
-- [x] [第十九章 类型信息](docs/book/19-Type-Information.md)
-- [x] [第二十章 泛型](docs/book/20-Generics.md)
-- [x] [第二十一章 数组](docs/book/21-Arrays.md)
-- [x] [第二十二章 枚举](docs/book/22-Enumerations.md)
-- [x] [第二十三章 注解](docs/book/23-Annotations.md)
-- [x] [第二十四章 并发编程](docs/book/24-Concurrent-Programming.md)
-- [ ] [第二十五章 设计模式](docs/book/25-Patterns.md)
-- [x] [附录:补充](docs/book/Appendix-Supplements.md)
-- [x] [附录:编程指南](docs/book/Appendix-Programming-Guidelines.md)
-- [x] [附录:文档注释](docs/book/Appendix-Javadoc.md)
-- [ ] [附录:对象传递和返回](docs/book/Appendix-Passing-and-Returning-Objects.md)
-- [x] [附录:流式 IO](docs/book/Appendix-IO-Streams.md)
-- [x] [附录:标准 IO](docs/book/Appendix-Standard-IO.md)
-- [x] [附录:新 IO](docs/book/Appendix-New-IO.md)
-- [x] [附录:理解 equals 和 hashCode 方法](docs/book/Appendix-Understanding-equals-and-hashCode.md)
-- [x] [附录:集合主题](docs/book/Appendix-Collection-Topics.md)
-- [x] [附录:并发底层原理](docs/book/Appendix-Low-Level-Concurrency.md)
-- [x] [附录:数据压缩](docs/book/Appendix-Data-Compression.md)
-- [x] [附录:对象序列化](docs/book/Appendix-Object-Serialization.md)
-- [ ] [附录:静态语言类型检查](docs/book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md)
-- [x] [附录:C++ 和 Java 的优良传统](docs/book/Appendix-The-Positive-Legacy-of-C-plus-plus-and-Java.md)
-- [ ] [附录:成为一名程序员](docs/book/Appendix-Becoming-a-Programmer.md)
+想要继续关注本书出版进度,请访问图灵社区:https://www.ituring.com.cn/book/2935
## 一起交流
@@ -66,54 +16,6 @@
-
-## 大事记
-
-- 2018-11-20 初始化项目
-
-## 原书资料
-
-
-

-
-
-- 作者: Bruce Eckel
-- ISBN: 9780981872520
-- 页数:2038
-- 发行:仅电子版
-
-## 示例代码
-
-- [gradle: OnJava8-Examples](https://github.com/BruceEckel/OnJava8-Examples)
-- [maven: OnJava8-Examples-Maven](https://github.com/sjsdfg/OnJava8-Examples-Maven)
-
-## 贡献者
-
-- 主译:[LingCoder](https://github.com/LingCoder),[sjsdfg](https://github.com/sjsdfg),[xiangflight](https://github.com/xiangflight)
-- 参译:[Langdon-Chen](https://github.com/Langdon-Chen),[1326670425](https://github.com/1326670425),[LortSir](https://github.com/LortSir)
-- 校对:[LingCoder](https://github.com/LingCoder),[jason31520](https://github.com/jason31520),[xiangflight](https://github.com/xiangflight),[nickChenyx](https://github.com/nickChenyx)
-
-## 翻译说明
-
-1. 本书排版布局和翻译风格上参考**阮一峰**老师的 [中文技术文档的写作规范](https://github.com/ruanyf/document-style-guide)
-2. 采用第一人称叙述。
-3. 由于中英行文差异,完全的逐字逐句翻译会很冗余啰嗦。所以本人在翻译过程中,去除了部分主题无关内容、重复描写。
-4. 译者在翻译中同时参考了谷歌、百度、有道翻译的译文。最后结合译者自己的理解进行本地化,尽量做到专业和言简意赅,方便大家更好的理解学习。
-5. 由于译者个人能力、时间有限,如有翻译错误和笔误的地方,还请大家批评指正!
-
-## 如何参与
-
-如果你想对本书做出一些贡献的话
-可以在阅读本书过程中帮忙校对,找 bug 错别字等等
-可以提出专业方面的修改建议
-可以把一些不尽人意的语句翻译的更好更有趣
-对于以上各类建议,请以 issue 或 pr 的形式发送,我看到之后会尽快处理
-使用 MarkDown 编辑器,md 语法格式进行文档翻译及排版工作
-完成之后 PullRequest
-如没问题的话,我会合并到主分支
-如不熟悉 md 排版,可不必纠结,我会在合并 pr 时代为排版
-如还有其它问题,欢迎发送 issue,谢谢~
-
## 开源协议
本项目基于 MIT 协议开源。
diff --git a/SUMMARY.md b/SUMMARY.md
deleted file mode 100644
index c7d1abb2..00000000
--- a/SUMMARY.md
+++ /dev/null
@@ -1,448 +0,0 @@
-
-
-### [译者的话](README.md)
-
-### [封面](book/00-On-Java-8.md)
-
-### [前言](book/00-Preface.md)
-
-### [简介](book/00-Introduction.md)
-
-### [第一章 对象的概念](book/01-What-is-an-Object.md)
- * [抽象](book/01-What-is-an-Object.md#抽象)
- * [接口](book/01-What-is-an-Object.md#接口)
- * [服务提供](book/01-What-is-an-Object.md#服务提供)
- * [封装](book/01-What-is-an-Object.md#封装)
- * [复用](book/01-What-is-an-Object.md#复用)
- * [继承](book/01-What-is-an-Object.md#继承)
- * [多态](book/01-What-is-an-Object.md#多态)
- * [单继承结构](book/01-What-is-an-Object.md#单继承结构)
- * [集合](book/01-What-is-an-Object.md#集合)
- * [对象创建与生命周期](book/01-What-is-an-Object.md#对象创建与生命周期)
- * [异常处理](book/01-What-is-an-Object.md#异常处理)
- * [本章小结](book/01-What-is-an-Object.md#本章小结)
-
-### [第二章 安装Java和本书用例](book/02-Installing-Java-and-the-Book-Examples.md)
- * [编辑器](book/02-Installing-Java-and-the-Book-Examples.md#编辑器)
- * [Shell](book/02-Installing-Java-and-the-Book-Examples.md#Shell)
- * [Java安装](book/02-Installing-Java-and-the-Book-Examples.md#Java安装)
- * [校验安装](book/02-Installing-Java-and-the-Book-Examples.md#校验安装)
- * [安装和运行代码示例](book/02-Installing-Java-and-the-Book-Examples.md#安装和运行代码示例)
-
-### [第三章 万物皆对象](book/03-Objects-Everywhere.md)
- * [对象操纵](book/03-Objects-Everywhere.md#对象操纵)
- * [对象创建](book/03-Objects-Everywhere.md#对象创建)
- * [代码注释](book/03-Objects-Everywhere.md#代码注释)
- * [对象清理](book/03-Objects-Everywhere.md#对象清理)
- * [类的创建](book/03-Objects-Everywhere.md#类的创建)
- * [程序编写](book/03-Objects-Everywhere.md#程序编写)
- * [小试牛刀](book/03-Objects-Everywhere.md#小试牛刀)
- * [编码风格](book/03-Objects-Everywhere.md#编码风格)
- * [本章小结](book/03-Objects-Everywhere.md#本章小结)
-
-### [第四章 运算符](book/04-Operators.md)
- * [开始使用](book/04-Operators.md#开始使用)
- * [优先级](book/04-Operators.md#优先级)
- * [赋值](book/04-Operators.md#赋值)
- * [算术运算符](book/04-Operators.md#算术运算符)
- * [递增和递减](book/04-Operators.md#递增和递减)
- * [关系运算符](book/04-Operators.md#关系运算符)
- * [逻辑运算符](book/04-Operators.md#逻辑运算符)
- * [字面值常量](book/04-Operators.md#字面值常量)
- * [位运算符](book/04-Operators.md#位运算符)
- * [移位运算符](book/04-Operators.md#移位运算符)
- * [三元运算符](book/04-Operators.md#三元运算符)
- * [字符串运算符](book/04-Operators.md#字符串运算符)
- * [常见陷阱](book/04-Operators.md#常见陷阱)
- * [类型转换](book/04-Operators.md#类型转换)
- * [Java没有sizeof](book/04-Operators.md#Java没有sizeof)
- * [运算符总结](book/04-Operators.md#运算符总结)
- * [本章小结](book/04-Operators.md#本章小结)
-
-### [第五章 控制流](book/05-Control-Flow.md)
- * [true和false](book/05-Control-Flow.md#true和false)
- * [if-else](book/05-Control-Flow.md#if-else)
- * [迭代语句](book/05-Control-Flow.md#迭代语句)
- * [for-in 语法](book/05-Control-Flow.md#for-in-语法)
- * [return](book/05-Control-Flow.md#return)
- * [break 和 continue](book/05-Control-Flow.md#break-和-continue)
- * [臭名昭著的 goto](book/05-Control-Flow.md#臭名昭著的-goto)
- * [switch](book/05-Control-Flow.md#switch)
- * [switch 字符串](book/05-Control-Flow.md#switch-字符串)
- * [本章小结](book/05-Control-Flow.md#本章小结)
-
-### [第六章 初始化和清理](book/06-Housekeeping.md)
- * [利用构造器保证初始化](book/06-Housekeeping.md#利用构造器保证初始化)
- * [方法重载](book/06-Housekeeping.md#方法重载)
- * [无参构造器](book/06-Housekeeping.md#无参构造器)
- * [this关键字](book/06-Housekeeping.md#this关键字)
- * [垃圾回收器](book/06-Housekeeping.md#垃圾回收器)
- * [成员初始化](book/06-Housekeeping.md#成员初始化)
- * [构造器初始化](book/06-Housekeeping.md#构造器初始化)
- * [数组初始化](book/06-Housekeeping.md#数组初始化)
- * [枚举类型](book/06-Housekeeping.md#枚举类型)
- * [本章小结](book/06-Housekeeping.md#本章小结)
-
-### [第七章 封装](book/07-Implementation-Hiding.md)
- * [包的概念](book/07-Implementation-Hiding.md#包的概念)
- * [访问权限修饰符](book/07-Implementation-Hiding.md#访问权限修饰符)
- * [接口和实现](book/07-Implementation-Hiding.md#接口和实现)
- * [类访问权限](book/07-Implementation-Hiding.md#类访问权限)
- * [本章小结](book/07-Implementation-Hiding.md#本章小结)
-
-### [第八章 复用](book/08-Reuse.md)
- * [组合语法](book/08-Reuse.md#组合语法)
- * [继承语法](book/08-Reuse.md#继承语法)
- * [委托](book/08-Reuse.md#委托)
- * [结合组合与继承](book/08-Reuse.md#结合组合与继承)
- * [组合与继承的选择](book/08-Reuse.md#组合与继承的选择)
- * [protected](book/08-Reuse.md#protected)
- * [向上转型](book/08-Reuse.md#向上转型)
- * [final关键字](book/08-Reuse.md#final关键字)
- * [类初始化和加载](book/08-Reuse.md#类初始化和加载)
- * [本章小结](book/08-Reuse.md#本章小结)
-
-### [第九章 多态](book/09-Polymorphism.md)
- * [向上转型回顾](book/09-Polymorphism.md#向上转型回顾)
- * [转机](book/09-Polymorphism.md#转机)
- * [构造器和多态](book/09-Polymorphism.md#构造器和多态)
- * [协变返回类型](book/09-Polymorphism.md#协变返回类型)
- * [使用继承设计](book/09-Polymorphism.md#使用继承设计)
- * [本章小结](book/09-Polymorphism.md#本章小结)
-
-### [第十章 接口](book/10-Interfaces.md)
- * [抽象类和方法](book/10-Interfaces.md#抽象类和方法)
- * [接口创建](book/10-Interfaces.md#接口创建)
- * [抽象类和接口](book/10-Interfaces.md#抽象类和接口)
- * [完全解耦](book/10-Interfaces.md#完全解耦)
- * [多接口结合](book/10-Interfaces.md#多接口结合)
- * [使用继承扩展接口](book/10-Interfaces.md#使用继承扩展接口)
- * [接口适配](book/10-Interfaces.md#接口适配)
- * [接口字段](book/10-Interfaces.md#接口字段)
- * [接口嵌套](book/10-Interfaces.md#接口嵌套)
- * [接口和工厂方法模式](book/10-Interfaces.md#接口和工厂方法模式)
- * [本章小结](book/10-Interfaces.md#本章小结)
-
-### [第十一章 内部类](book/11-Inner-Classes.md)
- * [创建内部类](book/11-Inner-Classes.md#创建内部类)
- * [链接外部类](book/11-Inner-Classes.md#链接外部类)
- * [使用 .this 和 .new](book/11-Inner-Classes.md#使用-this-和-new)
- * [内部类与向上转型](book/11-Inner-Classes.md#内部类与向上转型)
- * [内部类方法和作用域](book/11-Inner-Classes.md#内部类方法和作用域)
- * [匿名内部类](book/11-Inner-Classes.md#匿名内部类)
- * [嵌套类](book/11-Inner-Classes.md#嵌套类)
- * [为什么需要内部类](book/11-Inner-Classes.md#为什么需要内部类)
- * [继承内部类](book/11-Inner-Classes.md#继承内部类)
- * [内部类可以被覆盖么?](book/11-Inner-Classes.md#内部类可以被覆盖么?)
- * [局部内部类](book/11-Inner-Classes.md#局部内部类)
- * [内部类标识符](book/11-Inner-Classes.md#内部类标识符)
- * [本章小结](book/11-Inner-Classes.md#本章小结)
-
-### [第十二章 集合](book/12-Collections.md)
- * [泛型和类型安全的集合](book/12-Collections.md#泛型和类型安全的集合)
- * [基本概念](book/12-Collections.md#基本概念)
- * [添加元素组](book/12-Collections.md#添加元素组)
- * [集合的打印](book/12-Collections.md#集合的打印)
- * [列表List](book/12-Collections.md#列表List)
- * [迭代器Iterators](book/12-Collections.md#迭代器Iterators)
- * [链表LinkedList](book/12-Collections.md#链表LinkedList)
- * [堆栈Stack](book/12-Collections.md#堆栈Stack)
- * [集合Set](book/12-Collections.md#集合Set)
- * [映射Map](book/12-Collections.md#映射Map)
- * [队列Queue](book/12-Collections.md#队列Queue)
- * [集合与迭代器](book/12-Collections.md#集合与迭代器)
- * [for-in和迭代器](book/12-Collections.md#for-in和迭代器)
- * [本章小结](book/12-Collections.md#本章小结)
-
-### [第十三章 函数式编程](book/13-Functional-Programming.md)
- * [新旧对比](book/13-Functional-Programming.md#新旧对比)
- * [Lambda表达式](book/13-Functional-Programming.md#Lambda表达式)
- * [方法引用](book/13-Functional-Programming.md#方法引用)
- * [函数式接口](book/13-Functional-Programming.md#函数式接口)
- * [高阶函数](book/13-Functional-Programming.md#高阶函数)
- * [闭包](book/13-Functional-Programming.md#闭包)
- * [函数组合](book/13-Functional-Programming.md#函数组合)
- * [柯里化和部分求值](book/13-Functional-Programming.md#柯里化和部分求值)
- * [纯函数式编程](book/13-Functional-Programming.md#纯函数式编程)
- * [本章小结](book/13-Functional-Programming.md#本章小结)
-
-### [第十四章 流式编程](book/14-Streams.md)
- * [流支持](book/14-Streams.md#流支持)
- * [流创建](book/14-Streams.md#流创建)
- * [中间操作](book/14-Streams.md#中间操作)
- * [Optional类](book/14-Streams.md#Optional类)
- * [终端操作](book/14-Streams.md#终端操作)
- * [本章小结](book/14-Streams.md#本章小结)
-
-### [第十五章 异常](book/15-Exceptions.md)
- * [异常概念](book/15-Exceptions.md#异常概念)
- * [基本异常](book/15-Exceptions.md#基本异常)
- * [异常捕获](book/15-Exceptions.md#异常捕获)
- * [自定义异常](book/15-Exceptions.md#自定义异常)
- * [异常声明](book/15-Exceptions.md#异常声明)
- * [捕获所有异常](book/15-Exceptions.md#捕获所有异常)
- * [Java 标准异常](book/15-Exceptions.md#Java-标准异常)
- * [使用 finally 进行清理](book/15-Exceptions.md#使用-finally-进行清理)
- * [异常限制](book/15-Exceptions.md#异常限制)
- * [构造器](book/15-Exceptions.md#构造器)
- * [Try-With-Resources 用法](book/15-Exceptions.md#Try-With-Resources-用法)
- * [异常匹配](book/15-Exceptions.md#异常匹配)
- * [其他可选方式](book/15-Exceptions.md#其他可选方式)
- * [异常指南](book/15-Exceptions.md#异常指南)
- * [本章小结](book/15-Exceptions.md#本章小结)
- * [后记:Exception Bizarro World](book/15-Exceptions.md#后记:Exception-Bizarro-World)
-
-### [第十六章 代码校验](book/16-Validating-Your-Code.md)
- * [测试](book/16-Validating-Your-Code.md#测试)
- * [前置条件](book/16-Validating-Your-Code.md#前置条件)
- * [测试驱动开发](book/16-Validating-Your-Code.md#测试驱动开发)
- * [日志](book/16-Validating-Your-Code.md#日志)
- * [调试](book/16-Validating-Your-Code.md#调试)
- * [基准测试](book/16-Validating-Your-Code.md#基准测试)
- * [剖析和优化](book/16-Validating-Your-Code.md#剖析和优化)
- * [风格检测](book/16-Validating-Your-Code.md#风格检测)
- * [静态错误分析](book/16-Validating-Your-Code.md#静态错误分析)
- * [代码重审](book/16-Validating-Your-Code.md#代码重审)
- * [结对编程](book/16-Validating-Your-Code.md#结对编程)
- * [重构](book/16-Validating-Your-Code.md#重构)
- * [持续集成](book/16-Validating-Your-Code.md#持续集成)
- * [本章小结](book/16-Validating-Your-Code.md#本章小结)
-
-### [第十七章 文件](book/17-Files.md)
- * [文件和目录路径](book/17-Files.md#文件和目录路径)
- * [目录](book/17-Files.md#目录)
- * [文件系统](book/17-Files.md#文件系统)
- * [路径监听](book/17-Files.md#路径监听)
- * [文件查找](book/17-Files.md#文件查找)
- * [文件读写](book/17-Files.md#文件读写)
- * [本章小结](book/17-Files.md#本章小结)
-
-### [第十八章 字符串](book/18-Strings.md)
- * [字符串的不可变](book/18-Strings.md#字符串的不可变)
- * [+ 的重载与 StringBuilder](book/18-Strings.md#-的重载与-StringBuilder)
- * [意外递归](book/18-Strings.md#意外递归)
- * [字符串操作](book/18-Strings.md#字符串操作)
- * [格式化输出](book/18-Strings.md#格式化输出)
- * [正则表达式](book/18-Strings.md#正则表达式)
- * [扫描输入](book/18-Strings.md#扫描输入)
- * [StringTokenizer类](book/18-Strings.md#StringTokenizer类)
- * [本章小结](book/18-Strings.md#本章小结)
-
-### [第十九章 类型信息](book/19-Type-Information.md)
- * [为什么需要 RTTI](book/19-Type-Information.md#为什么需要-RTTI)
- * [Class 对象](book/19-Type-Information.md#Class-对象)
- * [类型转换检测](book/19-Type-Information.md#类型转换检测)
- * [注册工厂](book/19-Type-Information.md#注册工厂)
- * [类的等价比较](book/19-Type-Information.md#类的等价比较)
- * [反射:运行时类信息](book/19-Type-Information.md#反射:运行时类信息)
- * [动态代理](book/19-Type-Information.md#动态代理)
- * [Optional类](book/19-Type-Information.md#Optional类)
- * [接口和类型](book/19-Type-Information.md#接口和类型)
- * [本章小结](book/19-Type-Information.md#本章小结)
-
-### [第二十章 泛型](book/20-Generics.md)
- * [简单泛型](book/20-Generics.md#简单泛型)
- * [泛型接口](book/20-Generics.md#泛型接口)
- * [泛型方法](book/20-Generics.md#泛型方法)
- * [构建复杂模型](book/20-Generics.md#构建复杂模型)
- * [泛型擦除](book/20-Generics.md#泛型擦除)
- * [补偿擦除](book/20-Generics.md#补偿擦除)
- * [边界](book/20-Generics.md#边界)
- * [通配符](book/20-Generics.md#通配符)
- * [问题](book/20-Generics.md#问题)
- * [自限定的类型](book/20-Generics.md#自限定的类型)
- * [动态类型安全](book/20-Generics.md#动态类型安全)
- * [泛型异常](book/20-Generics.md#泛型异常)
- * [混型](book/20-Generics.md#混型)
- * [潜在类型机制](book/20-Generics.md#潜在类型机制)
- * [对缺乏潜在类型机制的补偿](book/20-Generics.md#对缺乏潜在类型机制的补偿)
- * [Java8 中的辅助潜在类型](book/20-Generics.md#Java8-中的辅助潜在类型)
- * [总结:类型转换真的如此之糟吗?](book/20-Generics.md#总结:类型转换真的如此之糟吗?)
- * [进阶阅读](book/20-Generics.md#进阶阅读)
-
-### [第二十一章 数组](book/21-Arrays.md)
- * [数组特性](book/21-Arrays.md#数组特性)
- * [一等对象](book/21-Arrays.md#一等对象)
- * [返回数组](book/21-Arrays.md#返回数组)
- * [多维数组](book/21-Arrays.md#多维数组)
- * [泛型数组](book/21-Arrays.md#泛型数组)
- * [Arrays的fill方法](book/21-Arrays.md#Arrays的fill方法)
- * [Arrays的setAll方法](book/21-Arrays.md#Arrays的setAll方法)
- * [增量生成](book/21-Arrays.md#增量生成)
- * [随机生成](book/21-Arrays.md#随机生成)
- * [泛型和基本数组](book/21-Arrays.md#泛型和基本数组)
- * [数组元素修改](book/21-Arrays.md#数组元素修改)
- * [数组并行](book/21-Arrays.md#数组并行)
- * [Arrays工具类](book/21-Arrays.md#Arrays工具类)
- * [数组拷贝](book/21-Arrays.md#数组拷贝)
- * [数组比较](book/21-Arrays.md#数组比较)
- * [流和数组](book/21-Arrays.md#流和数组)
- * [数组排序](book/21-Arrays.md#数组排序)
- * [Arrays.sort 的使用](book/21-Arrays.md#Arrayssort-的使用)
- * [并行排序](book/21-Arrays.md#并行排序)
- * [binarySearch二分查找](book/21-Arrays.md#binarySearch二分查找)
- * [parallelPrefix并行前缀](book/21-Arrays.md#parallelPrefix并行前缀)
- * [本章小结](book/21-Arrays.md#本章小结)
-
-### [第二十二章 枚举](book/22-Enumerations.md)
- * [基本 enum 特性](book/22-Enumerations.md#基本-enum-特性)
- * [方法添加](book/22-Enumerations.md#方法添加)
- * [switch 语句中的 enum](book/22-Enumerations.md#switch-语句中的-enum)
- * [values 方法的神秘之处](book/22-Enumerations.md#values-方法的神秘之处)
- * [实现而非继承](book/22-Enumerations.md#实现而非继承)
- * [随机选择](book/22-Enumerations.md#随机选择)
- * [使用接口组织枚举](book/22-Enumerations.md#使用接口组织枚举)
- * [使用 EnumSet 替代 Flags](book/22-Enumerations.md#使用-EnumSet-替代-Flags)
- * [使用 EnumMap](book/22-Enumerations.md#使用-EnumMap)
- * [常量特定方法](book/22-Enumerations.md#常量特定方法)
- * [多路分发](book/22-Enumerations.md#多路分发)
- * [本章小结](book/22-Enumerations.md#本章小结)
-
-### [第二十三章 注解](book/23-Annotations.md)
- * [基本语法](book/23-Annotations.md#基本语法)
- * [编写注解处理器](book/23-Annotations.md#编写注解处理器)
- * [使用javac处理注解](book/23-Annotations.md#使用javac处理注解)
- * [基于注解的单元测试](book/23-Annotations.md#基于注解的单元测试)
- * [本章小结](book/23-Annotations.md#本章小结)
-
-### [第二十四章 并发编程](book/24-Concurrent-Programming.md)
- * [术语问题](book/24-Concurrent-Programming.md#术语问题)
- * [并发的超能力](book/24-Concurrent-Programming.md#并发的超能力)
- * [并发为速度而生](book/24-Concurrent-Programming.md#并发为速度而生)
- * [四句格言](book/24-Concurrent-Programming.md#四句格言)
- * [残酷的真相](book/24-Concurrent-Programming.md#残酷的真相)
- * [本章其余部分](book/24-Concurrent-Programming.md#本章其余部分)
- * [并行流](book/24-Concurrent-Programming.md#并行流)
- * [创建和运行任务](book/24-Concurrent-Programming.md#创建和运行任务)
- * [终止耗时任务](book/24-Concurrent-Programming.md#终止耗时任务)
- * [CompletableFuture 类](book/24-Concurrent-Programming.md#CompletableFuture-类)
- * [死锁](book/24-Concurrent-Programming.md#死锁)
- * [构造方法非线程安全](book/24-Concurrent-Programming.md#构造方法非线程安全)
- * [复杂性和代价](book/24-Concurrent-Programming.md#复杂性和代价)
- * [本章小结](book/24-Concurrent-Programming.md#本章小结)
-
-### [第二十五章 设计模式](book/25-Patterns.md)
- * [概念](book/25-Patterns.md#概念)
- * [构建应用程序框架](book/25-Patterns.md#构建应用程序框架)
- * [面向实现](book/25-Patterns.md#面向实现)
- * [工厂模式](book/25-Patterns.md#工厂模式)
- * [函数对象](book/25-Patterns.md#函数对象)
- * [改变接口](book/25-Patterns.md#改变接口)
- * [解释器:运行时的弹性](book/25-Patterns.md#解释器:运行时的弹性)
- * [回调](book/25-Patterns.md#回调)
- * [多次调度](book/25-Patterns.md#多次调度)
- * [模式重构](book/25-Patterns.md#模式重构)
- * [抽象用法](book/25-Patterns.md#抽象用法)
- * [多次派遣](book/25-Patterns.md#多次派遣)
- * [访问者模式](book/25-Patterns.md#访问者模式)
- * [RTTI的优劣](book/25-Patterns.md#RTTI的优劣)
- * [本章小结](book/25-Patterns.md#本章小结)
-
-### [附录:成为一名程序员](book/Appendix-Becoming-a-Programmer.md)
- * [如何开始](book/Appendix-Becoming-a-Programmer.md#如何开始)
- * [码农生涯](book/Appendix-Becoming-a-Programmer.md#码农生涯)
- * [百分之五的神话](book/Appendix-Becoming-a-Programmer.md#百分之五的神话)
- * [重在动手](book/Appendix-Becoming-a-Programmer.md#重在动手)
- * [像打字般编程](book/Appendix-Becoming-a-Programmer.md#像打字般编程)
- * [做你喜欢的事](book/Appendix-Becoming-a-Programmer.md#做你喜欢的事)
-
-### [附录:静态语言类型检查](book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md)
- * [前言](book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md#前言)
- * [静态类型检查和测试](book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md#静态类型检查和测试)
- * [如何提升打字](book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md#如何提升打字)
- * [生产力的成本](book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md#生产力的成本)
- * [静态和动态](book/Appendix-Benefits-and-Costs-of-Static-Type-Checking.md#静态和动态)
-
-### [附录:集合主题](book/Appendix-Collection-Topics.md)
- * [示例数据](book/Appendix-Collection-Topics.md#示例数据)
- * [List行为](book/Appendix-Collection-Topics.md#List行为)
- * [Set行为](book/Appendix-Collection-Topics.md#Set行为)
- * [在Map中使用函数式操作](book/Appendix-Collection-Topics.md#在Map中使用函数式操作)
- * [选择Map片段](book/Appendix-Collection-Topics.md#选择Map片段)
- * [填充集合](book/Appendix-Collection-Topics.md#填充集合)
- * [使用享元(Flyweight)自定义Collection和Map](book/Appendix-Collection-Topics.md#使用享元(Flyweight)自定义Collection和Map)
- * [集合功能](book/Appendix-Collection-Topics.md#集合功能)
- * [可选操作](book/Appendix-Collection-Topics.md#可选操作)
- * [Set和存储顺序](book/Appendix-Collection-Topics.md#Set和存储顺序)
- * [队列](book/Appendix-Collection-Topics.md#队列)
- * [理解Map](book/Appendix-Collection-Topics.md#理解Map)
- * [集合工具类](book/Appendix-Collection-Topics.md#集合工具类)
- * [持有引用](book/Appendix-Collection-Topics.md#持有引用)
- * [Java 1.0 / 1.1 的集合类](book/Appendix-Collection-Topics.md#Java-10-11-的集合类)
- * [本章小结](book/Appendix-Collection-Topics.md#本章小结)
-
-### [附录:数据压缩](book/Appendix-Data-Compression.md)
- * [使用 Gzip 简单压缩](book/Appendix-Data-Compression.md#使用-Gzip-简单压缩)
- * [使用 zip 多文件存储](book/Appendix-Data-Compression.md#使用-zip-多文件存储)
- * [Java 的 jar](book/Appendix-Data-Compression.md#Java-的-jar)
-
-### [附录:流式IO](book/Appendix-IO-Streams.md)
- * [输入流类型](book/Appendix-IO-Streams.md#输入流类型)
- * [输出流类型](book/Appendix-IO-Streams.md#输出流类型)
- * [添加属性和有用的接口](book/Appendix-IO-Streams.md#添加属性和有用的接口)
- * [Reader和Writer](book/Appendix-IO-Streams.md#Reader和Writer)
- * [RandomAccessFile类](book/Appendix-IO-Streams.md#RandomAccessFile类)
- * [IO流典型用途](book/Appendix-IO-Streams.md#IO流典型用途)
- * [本章小结](book/Appendix-IO-Streams.md#本章小结)
-
-### [附录:文档注释](book/Appendix-Javadoc.md)
- * [句法规则](book/Appendix-Javadoc.md#句法规则)
- * [内嵌 HTML](book/Appendix-Javadoc.md#内嵌-HTML)
- * [示例标签](book/Appendix-Javadoc.md#示例标签)
- * [文档示例](book/Appendix-Javadoc.md#文档示例)
-
-### [附录:并发底层原理](book/Appendix-Low-Level-Concurrency.md)
- * [什么是线程?](book/Appendix-Low-Level-Concurrency.md#什么是线程?)
- * [异常捕获](book/Appendix-Low-Level-Concurrency.md#异常捕获)
- * [资源共享](book/Appendix-Low-Level-Concurrency.md#资源共享)
- * [volatile 关键字](book/Appendix-Low-Level-Concurrency.md#volatile-关键字)
- * [原子性](book/Appendix-Low-Level-Concurrency.md#原子性)
- * [临界区](book/Appendix-Low-Level-Concurrency.md#临界区)
- * [库组件](book/Appendix-Low-Level-Concurrency.md#库组件)
- * [本章小结](book/Appendix-Low-Level-Concurrency.md#本章小结)
-
-### [附录:新IO](book/Appendix-New-IO.md)
- * [ByteBuffer](book/Appendix-New-IO.md#ByteBuffer)
- * [数据转换](book/Appendix-New-IO.md#数据转换)
- * [基本类型获取](book/Appendix-New-IO.md#基本类型获取)
- * [视图缓冲区](book/Appendix-New-IO.md#视图缓冲区)
- * [缓冲区数据操作](book/Appendix-New-IO.md#缓冲区数据操作)
- * [ 内存映射文件](book/Appendix-New-IO.md#-内存映射文件)
- * [文件锁定](book/Appendix-New-IO.md#文件锁定)
-
-### [附录:对象序列化](book/Appendix-Object-Serialization.md)
- * [查找类](book/Appendix-Object-Serialization.md#查找类)
- * [控制序列化](book/Appendix-Object-Serialization.md#控制序列化)
- * [使用持久化](book/Appendix-Object-Serialization.md#使用持久化)
- * [XML](book/Appendix-Object-Serialization.md#XML)
-
-### [附录:对象传递和返回](book/Appendix-Passing-and-Returning-Objects.md)
- * [传递引用](book/Appendix-Passing-and-Returning-Objects.md#传递引用)
- * [本地拷贝](book/Appendix-Passing-and-Returning-Objects.md#本地拷贝)
- * [控制克隆](book/Appendix-Passing-and-Returning-Objects.md#控制克隆)
- * [不可变类](book/Appendix-Passing-and-Returning-Objects.md#不可变类)
- * [本章小结](book/Appendix-Passing-and-Returning-Objects.md#本章小结)
-
-### [附录:编程指南](book/Appendix-Programming-Guidelines.md)
- * [设计](book/Appendix-Programming-Guidelines.md#设计)
- * [实现](book/Appendix-Programming-Guidelines.md#实现)
-
-### [附录:标准IO](book/Appendix-Standard-IO.md)
- * [从标准输入中读取](book/Appendix-Standard-IO.md#从标准输入中读取)
- * [将 System.out 转换成 PrintWriter](book/Appendix-Standard-IO.md#将-Systemout-转换成-PrintWriter)
- * [重定向标准 I/O](book/Appendix-Standard-IO.md#重定向标准-IO)
- * [执行控制](book/Appendix-Standard-IO.md#执行控制)
-
-### [附录:补充](book/Appendix-Supplements.md)
- * [可下载的补充](book/Appendix-Supplements.md#可下载的补充)
- * [通过Thinking-in-C来巩固Java基础](book/Appendix-Supplements.md#通过Thinking-in-C来巩固Java基础)
- * [Hand-On Java 电子演示文稿](book/Appendix-Supplements.md#Hand-On-Java-电子演示文稿)
-
-### [附录:C++和Java的优良传统](book/Appendix-The-Positive-Legacy-of-C-plus-plus-and-Java.md)
-
-### [附录:理解equals和hashCode方法](book/Appendix-Understanding-equals-and-hashCode.md)
- * [equals规范](book/Appendix-Understanding-equals-and-hashCode.md#equals规范)
- * [哈希和哈希码](book/Appendix-Understanding-equals-and-hashCode.md#哈希和哈希码)
- * [调优 HashMap](book/Appendix-Understanding-equals-and-hashCode.md#调优-HashMap)
-
-### [词汇表](book/GLOSSARY.md)
\ No newline at end of file
diff --git a/book.json b/book.json
deleted file mode 100644
index 36f77afe..00000000
--- a/book.json
+++ /dev/null
@@ -1,31 +0,0 @@
-{
- "title": "《On Java 8》中文版",
- "author": "LingCoder",
- "description": "",
- "language": "zh-hans",
- "gitbook": "3.2.3",
- "styles": {
- "website": "styles/website.css",
- "ebook": "styles/ebook.css",
- "pdf": "styles/pdf.css",
- "mobi": "styles/mobi.css",
- "epub": "styles/epub.css"
- },
- "plugins": [
- "splitter",
- "edit-link",
- "search-pro",
- "emphasize",
- "toggle-chapters",
- "katex",
- "mermaid-gb3",
- "advanced-emoji",
- "include-codeblock"
- ],
- "pluginsConfig": {
- "edit-link": {
- "base": "https://github.com/lingcoder/OnJava8/edit/master",
- "label": "Edit This Page"
- }
- }
-}
diff --git a/cover.jpg b/cover.jpg
deleted file mode 100644
index 1819c2744826178e730b4927c9c7b24ebd06d111..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 117331
zcmbTdWl$YY_%(Rp;_iBJcXx*$?(XjHc5w&<2<|~cfZ!I~g1ZGLNN@;p;o=U<|9!W1
ztM=3G_SE#3>6+@(^HlfqoO9-V^?e(Fr6i{)2Y`VA0AM~Y!23Et27rWsfQSH(goucU
zjEsbWhKG)Zii$>zgNunrMnXYOMgjs+(y}v9QnS*4K#T%RtejlDyu1_)LSlm4qU=1p
z-2d|u7-VE*G*mPqbaWzaDi9U-|L6AJ2f#)GlENAQVWQg8DI_1q%QR0|dgt0pa1{;66r&d^`uhVZ-B4aY-TIYFZ*vd*X3N
zq!uI5NH_N5Yt2Dvd91u5kx>W;iHJ$)=ouK9n0fj51q6kJW&V?ulUGnw($>+{(>E|Q
zvbM3cvv+WG^7ird^A89FM}3Np`5YS;pO&7HnU$UMHTQc-Y1xnRipr{=P0cN>ZS5VM
z1A{}uBco&E6Y~p;OUo;(f7W((_x2ACkNzE>TwYz@+}_#<~@AizA~Dru8R&9?DTA%ZNsu>U!B(U1n=cuAJBpwT!SMXfJKdZ%>|onShJuFULq
z`_Z)UvT!mG3-ym`t4Q`~322VM;BA-tf$i&C=od*lWtBax@Y
zGUM+gqWOMZo$mn`YGEunjm0BVsxk9Od%PUw3;~)KYAAg{H!QgTNAt|a<3+zxs&G-v
zk@{m{vA=CqWidr0-B&E)B$CxFa>n&7I{RF5ef^XPm#O`wYes0&h%#O42&rSgLFg+RHUK>
zKR&~gt9PP?R7T@e`49Op4{HMpX|Eh_yR=@^voNFgDBj~hPH~zlkr+lDbkEzqzGwqZ
ziVTMtqf8MRgQ#nFavLV0yl&inL$FEM2Ebe>H8x446LGLaYA|Q9h5$f?OzUdmm#AA}
zRd3NXn*shq1mNK~`NBUr(WzcFD5;TQ6tx6;ofOisS_zsNk*G}Dk)`B0kcWi=#_a
z?GxdsleNsh#iEL!6&~I*8X{e`8SzZh@QtvpwX}5&d^s;gIKTd3K{V^<)uZ|FiEwgB
zQ4|j~iMZqzuGCMgp_=IsbNNa)}E)Qyy_AhL1)OG@lNo$FCDeiNoLEon2{QH0#_gc;ggHYk&=dNbqDP~
zmbKh%BOxj&f3bmfy+ug#_EZ@Mtcb>oxVGA0ofFj
z-{c=EGC8j|<~uCH-_s4D_xjer%`|o*C|Ekp_~LMNNt!Vc4M4LOtUBcWMj-3f9kp_*
zZ^S=7qLei|IbY+DvMSz)yi7db$A26kdf6wqk6C8PR_E*3kyiCbcSKD93xi9|*0tYI
z`jw^fvLCv&RwJ=Pjs#m0_@=g<^9DNVH98!?Y!1v*lauqe(N@Vguaj-4fV-JRtbEc=
zaG_?!*WnsFO4Wu>o(!%g_Rh2wWxN>vZ>t;VTy=I-PrJ}QwNpJFDn4V4UB#vK=ZGd@
z@q}=aXcATsp?1?jV9tT_A=RyzKzkzxXJhp97~&!M21x~R;6I{!iHT^R7AowFM?W_a
zg(J|l3h12FIJtB6RGr2_Piqi*;)uW4p#NOD-^%r%7e$yD@6W&MA^1b3HnV^H;zDU2
zB7`0-bUc2#xR_7_#HVHd?N4zmX%O9Je`o>_zjOS-R(^1luqWmiVEuab4hUGF)w7_cD9`DBtZ*nYxHzpADp_d65L{Tm8Yqt^MqxsBF
z%!%PQ_uuo{oN@FSKsewzZ42)8lpt)=nZ)nMD{FM=iq3?2tZvgxUJ8_#DJ(2+*z18*
zhGcc$;iB#Sq|Tb?y`|ID72%Y64|B#TAq4#KPBvP}72wRUbwxUY9%fSptgD!FDF8;9
zU>dm9Tf@q9#j)m%b`9>#MqprI+bvK%|F*dK+Qef`qhXY_{v6upq_r0BIiadD3Mrbp
z+Cb{leSPEfUdc7Pki+(dcvHJ0{HdPB+59^!>ZD@1h&3#$pFPm&Vnr8p3OOs8q9Ozo
z2JE)kEp4>`!w=}6zQ|(3h(0&5gG(@lvB-0
zbT?#Ov`}A(iRyQNh0}AU-hhTNos2cZ@w6|{2zv8-mS!{6V}VNM^TfB2ottVbGe?0o
z(Ua<&WjU1zov0U@+#-k3i6nYc{wuXs2zC!F9p4c2UINyBFKYjxcZ{|TGls)neP5D+>e*QPgLL-u!n1eK?rCf{={x2g^I
zN8sOu{1gvIlznJB@FBcjHVn%y#I&ZF^-E80w~0s`jCZQrm6t|>^w%wiAsO;WO!_)~do2FCEOl@M_v+OBh8ek~
zmrKyzO+d+LsA5qt><^HHBxpitET4ryS)2wjl(>&t_0o#7CiWj5mZVocxuPbqMn6
zMu_4iVxC5|JGFsY^lxJwL-9sD;W99PGrKwJMy)u^6?%;Ifi8IgE;qwkmJ?HDz|2`O
zC#h&H1b^Hyu@nD>o>=rd0hxTaD+=PL2#xS(HES4va3i~v
z3Lkk*5b;G1atixpnd=VBggsY?OHC^G8_Aah4N?$L9FuS?~BP!Fw(%{t8h39`CJzifwD5hxGkeWwFMAVeFdF
zQ7xTwM&?i);RX9%ME+5{e>OP=Wc{bq5p~-OhwDz@ts>1OsEiGbE(Os>t1lsDeTFNy
zw*DPpUEl|4#tLha(j=nljDBn|&bMDqvr;viCUz18@SpkhZ7-G?pOxu*gp3M_V#nLf
zb>oRh^-Hjc`TgvyJ9IafQG0{l5PjNau}PnkJi4wod=S`YPpqa^>@;tQu|0}rncY
z3e{qGsw-Waf8l6lBm3!>odF7g2TNISBJbbSi$7G;hW%NyAq@ksz(pm&MpItjvJ6un
z2RmH7es_6!1<;V4u+>I(g+gydbq44Ydjn&}$L`E8OH;1=cwB*XXO|GeRY;@3W28n`
zwxe08cac)2F;}#8+hIS^QT%Z?=8iH4&Uhf*!D6F43<`BZ_-tzaK~rCis=eA5<(2xH
zZ<(br$V$~I$o-=xzM{9KMbd%k>2XqdjzTjFzjsTn-dx~SaMQwK7q1d)NeaJ?(U4Wv
zb&xiog6^iZ5i%313)D^yk#3IN&&}4>tf`HE)@OY^FGV{#aWbu>fg)g*%V^*vl+VC&
zo4}hE1$EHgRU^^JQ8i$JUaDUz<+Vi&Vjae*r!9DF0F@i_AsXrk(k24;a
zo+@02(u#dFaA1-ZweY@zI*(PD2tg30lboH`AOoXz2sQtZvMnS1gYp0NVjyb9sEG1
zycsV^_4?`^w9L4fe8xyy=l~cdW%#aD8_e#*)=C2lpm}ZXD!G
z11`4*Cs?0czjp?S;H$qWzeu^DWlBIso{EbM>q$2g3~L6Cu>e{jt+vx
zS3}S~?Y0!_Y4-|9DYC~D#k>$#2lQWPD;cZb&?QXXeT@%!*~ZK`Iwx5Pi~7Zf=ylx6
z{akk9c{9UO^FS1BeJNT3Z&-_E-3s?{xcrmuK^+QZm=|TTb`PvkWz{fI-7k^HPC4%v
zjhNwNX4cIuqSftZ8G#g{3JesH3`y(*%pD%PyK-`#pg?bvt#rP`sT5VvT^nbkBDKZX
zzrhO2e*9a#>}o@2uxe}h4-?|Eb0ASE^LUpdMZUgyT36-gwca9)z$BB$=Q_{gh{Z^ZDG
zKYf?cDw(YVLND13Y83HIYUzTuaxn~};}VMm-@TOZU39+85=Q&Bv9FQ@AEl2z{bX9K
z9%nap7msfZnY52E_fT+(1iFpat#y
zaI(2H>wp_kZ)3l1FSx7}qA6TTWg)Uk%}!4e+%GIz{*^QLMjqfSJ-^$KuF&|aT~^c6
z+Y`$#^YU6?`d$tU^E=c>=gvdFVZq(HPhy8}g&Z4oQ+h&sl5*(Vo*2)=TT7$;CC&|R
zn0vEwC4RpnfeH?6cnQ%cK)+2Q;)RM~njzY!At4i5>*6l_1hvb?Got|u4ha*E84lOB$2RB#YH{FO`4onlX
zCix&*3j)Se8Vlx>2hh4s5IP_78tA7Nn*|;E6#E?
zAJv@be4?Pb&fwZ)YD@c`)lPWEXt;qj
zrRT8`0hcTRb?b`j$9`xr36fw0ibB#u?|@qCv8?>bOT4PT$K++0pIyt8OMI=%oxBUukQ1va
ztv2P!Vk8PQ+o6B6Dxbd0IWAW>SOj!+rd{dbp<*LVJPXPmT0&OXZQe
zM9=>zOzHpI2=|8Q5e}IXuz}JoLurUv>&sa%wPaw5mU9b~|457({pu`$+d>g#y~dBf
zHfpwrfT}^I_GqFsd;1{_6CC6{p#mNP#;{VaECnqOgS!DyD!-3cf}p@=moCZuJ;w_p
zjTfg&)V92L01~9Tfr;v+EwmlZizj)aI@fOrWnTU19YB3%j!=8#|I84VKhjPV#5NQv
zGHh=U%>1i!$(@yUNeeL?c=*Mt|7QU35I-bTSOrv5NJ4p(VDc8C;jKnNMj7vW9V|Xc
zpr*7@8JcflonH7O$$8v?ZYrMV1$4=nQX{Zt(wLM?BTVoDn;+_n_A!$eLp
zpNhN|jDn61Pxyt|N&caYdDa3T_Wbt-dl`&@>QGNfaXq8sKAAcUHfwO-oM;fP<;`6*tkGU$<;Cel)=qsDXIxNx&6#a{QDN|K`N46|4*9W}p
zuf4!}5piWvSs+zvU1YzYM}$zqP|7ruhkK6GK#}u!9w*1qp7o)2eG(DH?L9T>qICf_Pi`eHy}uURc2%}{qzA8etGNTcV7oGt
z|86I&%q!P8)_LS67K=yvN-P)r8u8F*srgFb&-{l%sotmFc|Uk!8dV}|p8ALeaKu1{
zSzQ0$gMeFH#c7O4oL3xx%Ld-%;<0g7G_>W!!?DvfO(50Y88-bIFHt8{RF_Rea^a>x
z$+?z$;_o^{GVilWI@K7nXFkkis4u&iKW?S3wF{P<)R^dDHu=q$a6yPt0Df^w&TjYY
z?!)kpqzMIYk?=o)K(|2rdr!_P+BxF4n_(TpEJgn4nT^O*p~_AXQk#)o6Xv?5y#y}p
z2709LqW}N)s$A>o#Fv)FovJEzq|3mrSf1ORZD;
zDSdbs5^gtSS#XQ8D^D14vD-W(S;ZboX~WevULD+X$oqT{dw3JS6qW!|FkutHNRp;a
zS4Rv{`C2?&Vv9ve-mV*WcxZn&}dfyfMhy^0N#
ztMIlTxqZC3zQd~}wHpH>lMwO_Fjs52T=WV|%~~%w3Y-m2b3U04Qt4i9CWUZMywVmiu&JN01hM>LDfj_9WdsJd93}S43(?j<0=ia
zowO!yG*0F;RhsOYy1Hz0Dmo``uercC-Fye=p$Dp}f5v_^M|%BUEqM^)b%L%l&9V|9Xf;!y9eYdog8dMJ+Rp#Oy5
z`l~asX1jfCjRMMv-9?IP3BchCQ|kgi8KLi&kX?l4yd7c1wW0}z5|w(y0!nHFw8t14Y?B;
zJ>(fg&YI=21hk;W?#2#dqf|4Y2$^gH5E)v$)_zro)jK6uI%&WDxSZ46U&U)B1fGWr
zdp>A$>|fu8$Z5|!kFSe&q!gWMVE6SgAgz-6j`;nP1lSOBM=Qinx@-4ppH
z>(K+G?+tz?{Z-B(;jHv3OS$kUr!pXaYdJCpT5VQ6#8?+)t-&3={_uVW{9FmTM3q|<
zmD>K&!=W5)*O}{Js9B~nQ5_@NIO>);uJ?D{oO)#-aP)=U73>`7dco^T{a-GB;!8c3
zpoP>MJ;cl(C6Mb=Kb@T5v9Zxs)QikcbwHhOqQn_=k|QmtsU*g=6!NGj2J=!)hA6?}
zO8dH{Y08zL*LXtZ)h@_(Gt9J$K*6|O*nFtfWnfQqv7F|iwI(-kWbIcAcrqWTZ0aW`
zQ_GpJZ8{5Xerx$!6D$oqkE%6s6#kT5?G2DVV4M09qcI3aA&39lKvV#fG4lR6x}@bjr#YCYQ?d>u+FuTRg8ii
z2kMCaAzE*M_foY$pPr^!u+$u72EmsZ$JV_Iyu^KzXIq#$S5ibjL7HTxGjXC3n}@`*
z#&}+XyK7scPu}hI1I8GZM|E-CqT~`-Kn+665(N`Hge38kr;c|Y`
ziIV6KA@zI^=+V0rIfI(V=5-$H(}o0>#6Q*v(l{*QnMEPuk1M6+b|Dz1{W-HO92-k;
z-4F0*vEd(~#FE$W{1AyO_sIzt_y2mW^x2myEb1rPX8OCqt+c#Q0v@P$rCz`ZMc?Us
z^yhOXiipo`NYr9biyj^`lhlOiC2D>CV$AI}Lgmt(eVtKfpkLzj3NPE8s9)
z^u;cj`%Z=Lqiz!12=%qx-vR#ntfAou5(Qw|rjaydPo{M|C)4pgCw9dbE|dB6J5R}g
zwxQ}goy+is#+J4=WfostBx;>an#3*s-#p>^^}RhZ&^@J}OE0Euzlt5nraKKLx#FcV
z8NArTj1Jj-k$p|oPM$1+Cp-4@uV-mf#KSE@@z;Xs;?%$RBI7qTsrufLmL=@H1IX&i
z&lg&rFpIa^B7$iL-y{i6XF?4@VIK>dJ-CJOD?8ZbW&wY-HDzGHU&Ln3FCTYo48Lsm
zRqa9!8d_Yjs*t)VbAa?Gg;Q&ux)2jFhVMw@Mdeb(jqIG&7Fc(x`RF0*y^yGQ5^bFt
zUOh}2t8;D^(xo4=LjiR7O9kC^BCHPrO^c>RxKqRT(SW!~wly<#2_0oYXk61l5`)9G
zP_Z1ljcMK*g?n#fy^Invl;t%LMdAxx*@IVzxCpN3w9n73mT@_jhHs>P6{qQsDEr;9
zk*$k5*7@8CpyVQwW3rSe08DN)<=b67Q#b8Z^CKDlLpp`G-+!vU47!|S7U(6
zeW4meXqI`>mx>>TmS=vX#aXHQBh;~mqn~Cxuae#Y1um&YE_%l_8NPIEa#MKd8?cfu
z>Ue$r;OmPoN~5w1#4sZ6Qi8|#MBb(w6DI7ON)0qn(UqcLgCy&3j-yk3#)IugX(+9T
z2b#0LJHv29J2FN{-FT9BkIH*ENA&1D#yBPW#G7{?+o-N2E%PbB(cLYi#vWSWqWRR7
zMUbn6uMo%$?pldBR%6=+bcG@8`$NS;P#66qY$P`?Rnt5*AzWhQ%V%j_AvDcSv~3UO
zE(Klxz^Gpe+Ns*i5Z6_64x%xk!`ygMXZ-z0gn)9J-|=a)Vf6WxI4~$&qzNGiLF6qc
zy?Iz#tKvP=;;u@Uw#o{NtWu%w8L5SP;w@!692iA-&X~GbDlneTbm-v6bx`W#sf$-1L7Kmfxk8+YU<%lgB
z9-6Hjg1nD8gH!7fi+2E@;tjcz$^6u)q>&Q8O)8V5o
z1^vgr^}o)xSh|(3BIwhZAHG6eNB%L%MX_>?9T)$^(EaG%%*Ofes8c6*<<<(^U*
zkoE0d*YT2bOHtnJ#Y05xs(1^8{)?jC`MJZ@p5kfZRChp{;Wm4zqutA-{Sbrx?PXPa
z2GQFz<_pd{U;r29KfmeqqMil74gT1@dyaJ@S#`&6fwpLuWg+V?I0|wH&l}6RY=$@+
zQw1tu{F9N-j=CFDU@SG~)b_Pj?lw`Tx;?|zNH%i6n4O$%%hsc)X-`6wc|%2#aKmgA
zzG%6u@C{X0So`=V9Ir-Q<@pk}i)JM)y|Ghj$T`YcN
z$UXsMDMM7ObhzS!_M(p}mk;ZnaLby8>sl9b?Xx*zpiK+p8&>-s<(jc{$HBY%$F5zB
zNwlD_PyMQ=uDVYtlKB;
z*BZp}*=J+G=FeVg8<>XZmH`VorYw8i34n;!I3y%*DNSsV(E
zV);s;N1yBYzOvDEDa*<^Sb5awG-!DRq3z%9{&HLK{rVzbzvYZOlsfLue!-?D&8Ptw
zKMh9|n^6rBt8g5za$H%{Sw;4TOCj4t*p>^+3@*m$ls}lL`8l#qD@SDOvK=XcCF>Y{
zu<`XAEZ=Y7y~n0zzLTtEBLQWic?ayO`fuTlnMbc3&$8Y5o}P*Zhw6?6V{5D>$Npdy
zC~Ilg5JOc^KWGm1-FlcEyeDUbmdzwO`=U3eE8+&GGucuR@r#?uOFe3RXp15B$`~x0
zLbH*VfuS(%qL@57Ut`2F5#J^adOt=pk;2zp`*jaPsFQ+G<86=5j09x~l=eK5SD?}Qj
z=mO;_f|M|*2bE&tmp$}9JM&m^GL2Ek9=VZ#M=AGXbH)60`VE3L$??96_<;I2FdSxD
z8_P6L<;8Pu(5(9CXWLb!JVi#{e)jq(@8^0`EBaO(f$`XABUwA7p6xnc64uN=9y926s*JNBlc
z@+>_}{c#)!Qt)|BGc6qi5j4k5zo=d&Mel}CD7VgC&=o4Uf6V9+H4)IINzxLuYl7BP&M
zb3KB+{;~WlhrUUI%@ell!@DIt^H&vm?|-kqIv?4J`1xsk)BkNIE)q(98d?imf4KWA
zRA>F3I0;b*KZ`i1m#Z<AO5rX&9sR-^{S)+ePz)$jHFS#hp%_&3mME;@k!s(apAf?^?cCw`DtS8hR?B9
zz}k?LIQ$BwSgp!7M%j02sbuda{E2j}WKMF}1RC{BwE*A-%8mLbl=>QHE%^1;HLk~B
zVRuH?J>fE$8pM4xi1mvrWx=2XWZys15m%DkAto!Prj#QyTf@1mZ&c8pznRXwT*@N<
z_5WaNL)w|~iwyfb-(77ERjb|U5#qRTYd-$QT}mlM8$C{$I!H-0PQ*K#GGg-nf+;m
zv=76KLe`DZbGp`z)D?_a`ZD~5rS-yO%z4PzZ{eSp^QI_Kp?O3z9~nd@Z0om*~}SpR8!njsI-)q)%NW%ckoTXPhx
za~IL9$$ZDW4Er%>)p~XL>%AIDSKEg(&%BIac*o5sD0^({raYLeTJsoe@Kj
z^8Oq5C%Z=}8qyGED*6=*idOJVIg7gm)AY&S$2TZ#A`z6Q%rt
z&);k;UcpOQZ7l?e9)B%z8V9oJz)wC^b9liiQ?>apg-n|*R?>n?c+@|TL{lV8?n}L7
zun*c+K=Z#ewncF7Ln>nw`q#U>t<#pAElA`rCB*{v7n05~7Um<@$JQsw|NQ9Oxti<)
zffjl-h$eyn)f-2(l*GUTG>J7b$B7%-^hH)LM?Mad8UisHyQp$
zVl?E@P2Och3o%5s5GU8_!W^ycqvf3H@GgItD766^AO#1QS+yjW5jH>1h+xttA{Am*
za%bysR$$OQw>}zssCkWn!LzELIek?V?hi`(ihqI;@x3)o&?<`uP7-2=L7L$E-I$og
z8(&n>(tj68?+?lR)?~_bOMd$AB*8j63MBIhRJP3$c2op?L83D`!P@6(U*7c(7Lm^N
zs#~OeL}5>ePyG$oRFF7+bwiGJ^*<-V1Pmz&qj4cNbfdVh6rawIQgKMT%sFrMX)$M7
zeO}oi!Q!n`RH?P}=^lo1LV|)6u@w?K>~n{OJZ!a7o~*V?XK-0!Ps_FWohHJjJr}8+
zsFejJW0VmK=(8pXZ@f#2t9o&%-o<8{e`ekBG=B`EndVqvDh+*jT)cJoE4h+jP=D+O
z_m7s7$@=k_{hK>p80G7bq!~&)$dBq;S+4liQ!>fdjAdp;R?5Q*;KmY!yT6dmYmHXo
z>PW_j-o;Bf`&A$uJRZDveONo|xF>=YBZ1|VXMX-#q?b|jVa!=QUGuF?NO~IXEutZ~
zdYkg{>?3~i)|RO~uK1Vw_jq10hFTGO1xO}%p{RJrki|e3=)9{cOQ0%!s__fEC>tV>
zriAy5U_C9lM(~4(#%R2~PUjqs&re2czPvT>ewk|%NBXBoRAIpk({kgQvUguHm>tRS
z!SnG_=kN)UndfE;_u+c*iB)gSE4AF{K-X+u05yyDWp#Z2o-b}!c?&C`>cRBnZn%yB
zK9++fHXSKJN#YQ8gQF=PL|EN{loU_OpbED~k
zl2b~1312MInbH*&NIE1|i0i&H3!p^0Z5M^C{ab=SYzM)E#H0+!-bDe+CRBRjHxUJ*jy(OUkvRy=wW@;gNO-9
z<|k=|!%w5MUQB;d>!A9LeT%9lk4TArcE3?2%6vQ
z$D?r+H)`C#;OaY8QCL>Coltd9eI67Nb8^A4Rz1V`fhoY+a3;ov8UaK=F3{gme2jhlKM!pmp%AK;nBqZ)hS+Xi_Xo2
z%VkeODJ8&s@G*_p=O#AxPf4nq8c!0F&YkxLz7S2@J0Lo9`@t$Jz_)@Si`J0?51_1vh~~ZYQRlBf$4e<`sn%(
zct4yM;ifM-SO!keb;-HF=yI8>D+EkDhHy7!1Xpi$&X~ScbMfgYqy7=>h9DtOfEr;v
zL$6a?Y5$>fr%q5D!X4WAM;;g183RQP?9w+`SjD3yzz_%uaV&yHIJXL9%}e>Zq_xt=
z=%ggplv5_$!|8UWtP0TvO?41rY~GU`mOq5;kam5}az(*qoiW|C&lC_6qJ>y)q??5u
z1uMk}6bj}a}rU3nn~zTvp492K3tV1ylix9cc}7R8=h
zWNW$7LsC~K7VwB%(%bjMJIasm{xU+(E8$zUakS7awSbHyuOPMwF&5&Q
z`LNs{X5rqU3%s>4s~%`6tZl#LPlZ`AsN%5w!4P@ho?kN=sYzQ`%YjRo
z!}2^`CH3``HqY5U}a7t^q44IHE9vDSB<$0
z+vOiYj=T->o)M~7RR2yL=O)W{1=90RKq0_onlrdcjlei&RQ(cFb&<~*=8R+Y`e<5a48fYeu!8{@Mn(tFzzb?=9ba
zFcU$S&}{8YJ3I~^j?`GU)-Xs<%0I(TWSZblj0ucoIS}|ugc$X=XKPToss9P<9Z=!h
z1@@JCE1nAkU&3bo0Wmn5#dPmsw_`=mk1rS
zZ8wH;hME%+&CT=YrA6tJL4u4-5T}_2nE-oF?y+pj?;q
z6n!hgu~|fr4pV8*cEho`(~;ZG)^YBRI7_MZfae$fnl|Mpts>r5XXRp42ND)I
zmz?nYN18!qB@U(q@+xmyPww55(SLs&4QOfxSbuNDq`^v|l
z->PGQjMMiDlu_{kXjM8931Ng_)2}W!CSZ+;KoBR5=-oFy8miXlS@8`11KsD+`@QlO
z1$9b`kPxQ2$@bT6@BUe$4|-1{)0P%nb)2$b!@8jyUU1MNYK50M6V8=o1_P`OL+Z?3
zcO5Py_^nP`f(7{7uGF(l$ZjuzjW_X%{ZJPUbkqV%6o`Vc*$38CLml7G_xT=9%>SkG
zKT<4WSg3+!A4B2oI%u)ZU2
z*1#H(9@0j{HATyw=j}hCy9#X4@zxRBB%DE~$G*LlbR}*_12+MCMpk#y!)Mk~|3`KF
zJvrmNsX52EfzOda*ZNRjZl9qoT)5iT`y~*7YW9?=f^}@*us1Q(bes
z>MrqLoX^yzZ||<5*DUn~6(x;&!jT$G4E`lVbTey&g9TellqrAVk*w
zL3wa=n4G?OZZgL@-6wsloz7Y_z3q2l)J8n@qqRrD0%z+Go~xMp^g_I666X{l97X|p
z2#x!;1mfB{TX!hQ!oJkVY3$32`vb1c(Pf3*gYS07+dCizqAhVfA^$;vNLd<&*rA^d
zPt4{Aw*>nL-Wo|)j-26u^?yU4^?frE`>>~Pkk`IffmB11t^Q4d5OF!^^M;}M_a<3T
z+E?q0z4L;NguM#U5T+Vg{xb%Gfbg~v(tTTCxllR$V<+eAN>Qz_z%{j=NR+jN09gk@
zkH7ST>UXC?qIo{z7BVg3^RwN8WdW@!Qz=1su(#1-hDF^_`oBP~_I61?d%gwqyBuW*
zLO>2J?&mG8t%l{NZ0k*gV6T3SJHS>
zUsLT=ED{pD-@uFg1J065Zl=O-^$igrOk_{qPdZ`N`aT78qhDXQ5n6cSQGw!si?QeF9wfls9$3_8#lko*&*SwH?I)
zve90rUi%7fGLnG#Ha6@znZ!@a66BE#4CGKC{^8UimSRuwdqdEABtThM^QHtU9S2yS@Yon+yxw$wuLsc9@wuEBj<%0I!m9=k
zlvI+xf*4rrEbL?ER$OAfCfm-K6=a{t^T!`Mq3EAep#ZS3WD8#@1B|Zg-*K$CmyF5&
zL;3Zm!aNLaTL!VMSOEGMzNx6?w^{0ec~g0}5)Ub?jXDf@!DF+43lI&vE+Mf<^5chJ
z>-)26X|o_O%pR#OM-(Z$L~V<3BvFQ3ew2}_tdOy`0;<*?Dlv}Q%2v-S>&R`
zP~*9&FHFFK2A8_{IC*@r%7RIzBrCnvfNrce3Mc-XE#{+(HCFY+e|ZZ|qoxh@>YYL&
zRXqBAZImsbkIZVZF_j`&bDhc39^4HxDw_LPtc>QGrYkgN`ifa^)}Z#5h*9J
z3`%`m@L>pny>yzo-!$}i
zqWjyv58#b&7yDGWsx*$gzT&^103z1?eM~E-jbH4Sv=IWQZGFR2fvz>;pESqCYl0^m
z&tnD^vSxP5TAOnP{#`k)OIdg>VyJlu*6fr7n5}CY*7+2$6WO&1L0yxRA?
zoetz{OA6Mts;aErU2_VIygu{p;dipr;rwZ6A
z&nTeL0ahXke?t&{e{cBD_v_DXD5kqn^e?givsb#0B*X2jl#-BkJ0c<+`7~iA7c<_B
z#ot`~a3-XPF%j~a;X_0&lrU;S95w~7;Ttr+vP?lJKSg@yM@_RE#p_EqJr+h04iuqT
zF*u7<#Eu2e2*G_gK1_7&9<+Dv6ib_OwP;lv>`Vv!g*N0hQ%$}-bk)qdG?+Q+;YJRI
zj@phPiY4P)t?xGL&GOHpArUXQxT0^V*jKEd>K$lX8X4zOKr8f|1toTED6J6l;pkfJ
zpF5~ainhzr-2GQb{Wyth2$M&B4Wsthy8kFc5DxMC=!)CX!l)6iODXVf6ls{B{F)Qg
z42@(d0pP2xG9_<)sSANh`8PbsZFNyoK%t;@qJK)t&lGtvpwDi#!~n$4S+`x)TfN}N
z2r2^n&!F`D+%*cEo9Y6KvHB2q7t2-CJ@oW-X3QRSiXn8^wdMKM+S7gvj2)DH?kkD-
zY|*Fh9Y%|1%`{>eeow4fQ@vI{>Dmdtz1z>|tZ$*ixGU8%uJfv<=N2x16l|3dQMZ^62rN8akE7
z@pV5(!p9aWqr;gw0l?G0<vMeKZhcttz6c==kF${`bo7zTsi#3VeCd{9l6R#p`|#x0$9q(QN|&%{ZEe=Eq_1A
zM#n#GD<{(xhio)_g?9VtrFyy5|HP_DkI&biu+Vh4ISZQqDOZljj;uil3Zr-zrf?$Ont
z{8$`+$eT|S$0bS{gXp?C3f}Ej-)4i=q#I&<@*Q_W12m&;z_eQ*?7!jv-5j9}mrGYj
z+w*!1k^lAgGkHc<>wm`F3jPQp1+5TP??S0#>2=NPiT?wqKv=)_K7R2AgMZ<6OD#e@
z{&?T!MhT6NW4f>xm0&O%srIj=d`D>(qo>PZe*|(`&GP)CE{C&$?OqkG_DMicPy^fl5Qqaha^C8H<{&e3ce9SPwpOkIM0;OV^U)|>;AP&_Y
z?ahQ>tB&5a9V~2^-z`aH+mHw&1cUUU@Qt0o5yu0)A#fWTw*Yg+BkkSULF5xiL(Gg*
zZa!mxPqi_*J9E!Nng?K`k;$i)VhK^ltueMj!BxKKARcL1K^wM=6OcF<1E8lV2XF)u
zI`Nuosxu#%k2v{9N(2nR$h%bJ^yh(1ZVApv&&`3*(~c89UUTcz{{Z!==&QMziNPHD
z(gC|!M^lnAYA_V%q4mhA3a{M-q(jrO98_Ty9f1m09nLUnmcnAmvjc8&4+GHAPG;Ik
z;Df=UfFRa9HL2-3eYO4Vrv7F%;hD4LvY8YTPFM`|
z6@TE^4ddzLQb=7YXB>aiNQd>T?Q_k44^8GJ$CR=l49HiLjybJgg7JgnO-0xEG`B5_pm|_Tn_IS`^gfW;s5`xcGm>noo*sCA`ummPn$P$&gDEBP(DW5PI-?
zR?WZse5N{XuQvED5Bwrpn`3Tu0y!RtE7GmMmh1=lI4=1LTYCrN4*URfWwwm&8`{}rhbIB+A*VQ^gd3pwuANMR^ACd~{
z#e683Zd^tv;fGLb=f8;_9#0SW##rEsWsakZn_#Pj1)C0@*gd-fwe%fwe-XSo{vz5xi)w|NnV5dSyxlmV`t+!O5d^*y$H+#(+ySR=UAu6385kVX
zRBy-K+u28Y80FM$%LBpBO7zTu3bK)&oQ&6d@Pf!)cVG=$
zYfp(DGn)F^-}_-?Gfx~}HMC=^0Dp(yv9EiW1)0=z2Nl6mlZO3GE_wIHISTk9)pAb#
zMn3+C=Dbl483dnSYW8o8ueZXwQs?jLKA9Xw_2XP%t1#pHqqTM6zlKDQM)*CZiM&sJ
zsxoD4ZG5=T_hgXu9{WQN#=Vi>&Hn&csVDpBt^CDs{{RX!zp!{9UO)QXPT}q`+(y45
zkNkC;@vgT~zJpA#Yul21m69lr)=30o^cj(>U|A%NH5vb+Ug|ub(_q
zYBbLn>sDJ8Vv6zE6;}aO{&fHjgA6O^)>4i^7$Uq&;=PEo@zUNPZMub=a<`$8GZ`O}
zrCu6d^G~oyv+$$w7iicj^YD6L5NUFu+QS3t$HhXAHq(4Zw^@d?F_%j
z*Oq)Rx@%7#Sw_bRdknVBduM5IGxb~#t$T$mM>J>Z3dhgBFVi8>{AH`yT12o~$09Up
zq>!q}jgE7`-B-SJDVvzW1`%>G9FRuKsf9ae<1L?~@>03G4k1`J;%%2H-Eg|_IRfzQc
z-OxY!5}NZr7ik)Pf#QpeCrg^{;ca1$&U?33JJ@7}DxhEnQPZw#=ru8+GD^WCLApm{
zfUAs>Pizir=8Z=6wVhh;QjrNabG+X-@PgS<_zVh~4sve&0qAOYKf`0iULpR^l4gP=
zf##M}P|Uc%00Zhs{cE*924To4;#t0rW~cc*Kj7w@vrX0Yr|WY%+C&J(7BRVq_9gNE
z006H_9MsjVH9lDM8b_BOgD%WAc##MvqgoOCn!M)v*|gn8`%kz{@>^Uw}E`RrJ1kdsl;eNV8i{h#IB`%W>u0FB~1nGDqSKIu#`*(-S#`>dk?L923>4@3-V3
zST|A!Bk`qHljbO(j+nCg?{UkbVY^Bx!RHJZz{A8`Sc5_@OqUqE<2PlrnIc9jeR25V^UW^eDwB8DWNY~XtV
zSyi7TZiIO(o(J(tkYw=n)<<<@Y<^5?ANWN4NSRmg{-yr;h_-(!_rMtE2LKG8YErTQ
zNX`db9M?L;$fSJfbERsQNYh>E7xu`b=8^5(D*Ka;Dw{I-45hH8bGxrTwe+&e>Ud-6
z*1RXjx<#&s;)~l`HCXMQG`Wg2AL@e+KplodV0IW4r8>O#PeC)^Em0rC_IsUk_C&)l
zAKe_&)rwpl(r=Kk0Tl6qI^+KUuUMt0ywUXet@f-c@meoa(JC)*=!YG%TU93;F0O{tCC5{g;@E8c>e$#)=Wk_xs%F2
zxhwmoQb|w}uNyTfqjOMRm%0_ME+Zv3VWNjy&
zrx4A{Dv!Z&m4R+d7y##
z_pPnm!cw-y*n~0W6>qva6PyovE^VW`k7G27I3S}HKb>Wuia89hd9pjV%vcr9f7-|C
zR$0u)KWSLiNeUa~Y>vF=kwb_nC(v}3@jzBmgs>r1i7a{cs2tz3ym3hgPQa(coc+
zO#1H5R+VOzp)Qh>A{?T(9Cy#C_o_{E_H9XEkQBJM%PU5NrUo(_(DEt8MANL1vn0EU
zkmsCt09A76Pqb!)WiR4c86GJR;1UMqBd$8vA@MfS-s{6|lM>RxjU*%tmSMvVo|V%J
zwuH+L(j@?@Cj@612R`+as#={|$H;d}WmP+*VYn){3_iK1PAN?{v7(lqXMjWH>yEujmkzrABATks{E>U4#&6BvYNDy
zL2Ypziu|E|P;$-fL!nsLETdjpEGqmk6L?e4awV{r*?BpASoX=
zO!S}!gk=Zj2k`4g*2&tXMmZqoKGZ6(2W}6!IHr%jH!eLsZuAAjlW{@!fd{TX!kWl8
zZu`V_sh4XWeK{1kRwanWKb-`uikDk@0u!x;m^+Ce>u>s?ojqDbuYz_Cdi`H}|Q#P;{;T%xYw
z@(!m2k&niRY&rZ^FX?*DqoLfr-kW;%vq>3^nFdJ*oL6T&_ct0Ik*VIBi6^*)%S|I>
zInFwE>0W-xn3xV69tbtrs;YQXMBEWbMg#YogB+jX?M*^I5j{%!t>m{p7rs_;#L4-L
zbo{Gt;EHe7HM!4N?BZPgT%Y}xu>3)9D_OPIkrG3cR!I5->yO5|e}V`We-oefEdU)3
z(q;bu>sLKZDL?C}qk5jQI*+KYoV<4@neh+A4ZDGOLFcllAJV>z8OZgne^Kx+g!OCb
zudlQ?WxAcq%OILWEXUVtV?0+i3X!J$;mJ3#gYb2K;)uF$?`l$y$x^)nH}crY{l#PX
z15`AP8%@wO;bElNi(5eEPb@n&S+SB?$t3VPp4C0$`Fdsahxjd}Z>A9c0QKr7`KH?H
z!=dtoL5`4_UOcbqUs+qAj>^(8(O`{7;GkE^3c0Y2PJZf+zPPWf_LWH2(lsBFis{9@
zg#w-SrEjLag4~j#`tfX|Zp$G@VV`5SZ`6vmK~h2LE6+YOGpB=eqZ5>rYZ1I|4hofu
zToLXKb-owZ*Tnu9veo`kG>fv~SE9_g3tK(a9;n?soi-!7r!Bs=}s3o!F=%X1t6&zr3PgE^}tDKH`rBwhB2?Pv+
zY03jC;~R%ej%(2~Ixh_P3tRDKl`a08bEd@=y~|rLyOu>_!BxM72>viX3f4afd|7N7
zXOl#cQA;-4m(DOrz+@e(wD>-Odk*HYv+#%_;*{6#aFkiv9<7dv{e;M+`|MU;qVu4BvSBoYdl)y0K9_)8k9yM9|b9y?Y~mN&f)XuON~s
zALO@<-gz*ws*JNS-~c<4O?t=1rvCs(@Zx&OaNm-~Kdo{f4|MPCPao+>-!fY}>4rftS=Sq7P~#rpAM0Lc@s`hZhKGNQd3O?97C-GK;6L%k{HwdrR_;FxXz|~`
z@ZQH|6f?%y+^(tvWR4C<&j-C?d`hre?}xgH*bCXTcTwlI))_zd!!;C|jZc`m9wTLV
z+HR?1ey5vDsOBH=76ktQD*A3vzH1dAsW}+*>MP~B6gm}96-ec=Uq*OaQ5wI5G;8qX
znp;F!5B)Sxk^cbk`h@Q
z{_RK9X=`(q_=TtqKfrpK--o+VWSsRfa6tb6fCl|*z?_Jq@01&|4;AVE02p-^d)*^Q
zN6N(;-N=CTW;;-k>;wL0xIGt7I^T$Ny)1(1b8?94c=u9Pqm81+aeIY@?sN7C`Pl?}UHWx_MuG
z%-nK#uO;}|d|YVyLJ~)pE!2zD5^#u5(+~OAB{k1bt&!_fC`p}r1I2kC#w#6~zKf}<
z?lap-Z2p7GV9WTCA^fY;^t-cvq3M@|{L|V*=jv2v_04i07HvM!;K**a<*hGKiT?m)
zfkXP0qKoCJ_ygGSle-wIvr|VK5kryi59tT`f0#xIm8RI081=z3bOL1hSEOnGA!^QEjZUESK+qX9JXqzc&Mb1+bUTKXSH(i1__
zE%dnV?rxIYU`cYpo9Vz9QP2*<9Gd0C+Q|&W_=TrxTCap!*GjjVd4AIyNenDio-htT
z!36SDk?1Rr@D78o*!b4k;_pk;EiDo`eAby+P=gr&9Go6@kUMp+S_)gBC+SMtv-58J
zb67^Jj5$U&ykp{Ito}N^8TnGy6c{}|P2c-B>t4{f+zA;K;XXan^({ZeHMnNa@e)xv0E}lnx>f6lZQ`+8
zb#_SZBrN2%cPJeJ_xVL)iDT3B>qug{xN@3pvqJz*WCWf!0guntuS&vuhOjz=8DuI1
zawy*jBXPk49lO_5Vx?DIjGMJPj{8#mmt?XVStOB5BqS*W^i!VL^sDeo6fq~2eH;j~
z7=rEl?UA3na!!uk=~UB9wz|ER_B%Z-uH5|1aLpmf
z>$C%m{VTpvO@!O$D
z3PU*q_h6ii_uAd6C?t|snCbzhi4-ET#CG%Dm#%%qR+?4?L^8`L2N}BnfIU@*Ap07w
zuPiqrWiv|bF%vWLq#m4bMQEwHN6dw}&@B7y)fzY*Py(&HA+Ucjk9vycdFN!BB_)?7
zNd6FeoPFV0m(bl^T%?8vw75mcnMm^75y)k3wJn;oFo%OtR$w?$8Noiljs-%5Qor^1
z4Y^*|G;HUVRbzG$CSD7t0f%kAw35fVRi5S0!Vk*5$>?gls|}cit{k+kOEFkjjGp)$
zfl|f$`>Royq={omYA{pwvvC-!uf(ZU_w
zcI_t^&q7Tkad~Xb=B>ZYovVzIo;OsINet0RH<~1aa6c~~kT5_sF4rvapNN*SN2@`o
z9RC2MTOeg41z2!L>0DzlU_Mf+2SR#RrTkKfR>w>>@r<BAh|muB^R!0m-Fx
zQth}dbHNk{LYx+LDhEN1l+dw^@~eT6eQ8(k0}LmW
zdQwYmI}Zl{=lRkwDn{l2_Y2Q7pF2p28i!{gR|mQ8MYh!x=G|fH;B8eHDj`cZhYy5Gno>BbO}QRV^pAY@yK#d&V3U)Nn0BvRy|o`|dA#r!azeQ;
zz1=&VF_*q^o;1H{?W`k>R7D)p6(w+3ayidh<>Hfp&f|}lw-wjwnhox<)@g3=AcdK?
zNc`aEuf1irg*8UyXSE=8`S>4Nm`W*Fxv6tp!*LvlK~)*Z9P`q<8JPb7!Y!f^@|1|PNpk}3vCj{NIV{afdGS#ZiLj@
znfr7tWo+S2*0Z)YHg3LW0e6p^=~eDDT|(atHH&}_(mL{bQ;r^*
z)e7?1paQPI%mRiTP5>NoPip#cyi4K9q+=I|^k*OJ>JcCPn!azCyor_e
zfg2CuCmm}S;U2&JpW+F$NuOn|q&Gwf!ldd6$j<|C8-2>C^sXXZ7XHpPl1(;f!>;9F
z9(OOV9jXUb*t?ap>$e<(N;Koi$h8N}eNU={E>Frc{^`wmAI8w>sOSn;7`L39{{Xy|
z=25`l5{)w8WbI}c9=&Qpcc3y!B%6Lwy@@J1@tTTweo1p);N-|qDZ;m0V1_uQ48|>>
z7TRz-nnC3TZL*A$(=?~cOtD}NaB^@7^{$dnY4|;T9oK`dY!#26WqToX{w3pbNPe-q`xnYr>=Wr{fK+yHK}%qyxIfKbZa)r~d%L*zth`3AEHd-djPq
zerFl_iqGn^@++9v_|0(?y3T{Aw1H)|ww`z6KkFGn4`chL{{SYe{20>|Cbg`x<(p-k
zFX+E{@#+ck{{SlUOWW(MOHi8s08qGVo4L7?S0gRg01ki-fDQ$99vk?Lf8l)&Eh^JV
zvABt3c}vL5tmT_II5^;7bm%LhRORfHB0_rH_hnMd6-OtvSC3HB<^KRzsaU^nmgx`m
zuP#rF`i>hO9ktzzD<#u>ryMp4o}5>gMQa*HV)9Z&10Qig&)3$mh89lz+84}yQVOu#
zj*hv;QGxwML4RlcrKMk3b^BGkkp3k|AFX(&fjn_%;LSer%3U(%<~xbRs9|**Ft{M@
z>zoShVED)3@aoN^>uTWiSm9y+0HXy&s7^A|R0>*Zc-_3dWxPzxRP7xHB-gckD7*9g
z9VMYTHkXd8&qZ(?ex<9&@8-6bRKAwQ8EquFl1p`P0a(it1_2`=9Cfb0;m?Zn?+sk)
zNvlX5%<>g>~1DG&B-Dr;$pEUDZMAaa^kWNAQW;yH%AkI4x-?
z&;C16>K_q&Hx7+`J%+6u_i1e*w~1nK&n6Dh$n_$)6*=u@R)>`Mw^aVz@rJ9Y#@Ua~
zXky!+^>O@wkFL_+Qfs34NvDgy6kcji7%5?FRy?1(B!?OQ0KP+y#<&CxdA>mwYZW79dJ>I!ThMo
zxFCU!gyWj^7>nK=R(}-eYx47{+T?e~nwhVnWadUa^Itn?w-IUHA<{1Et(m8=dyp$NRVZ?_I}2V-@n`1oEsE{V%{5yo>?`d6&++~T}*;-sSE
z#w;N!#@5C=c@&@G-0nx@>rW5y{DjX>@a?NZ;cH7(F+JDza&O%uNw^&C>UwqK-kl<+
z@9ss+ae0C^+Zup!0S-^;RIT3HEiX^Fia6S7blY@M7C;z0laH-Vh||d`KBI39tXDf?
zjK&V(kC+zp$vpcC?1Z^$re@=MPURV97W3Oi-dxfd8RPR1unC^52U2@h*OMWD%l2O5PS3zmB7#SuCzDd8#8O(dz;=_&0a+L4D~>USA6j4SB(!t(
ziP(8VnGO0YtK2*(Ii
zsU6u*6{Brxwo(;_*-W5$tn4{<9389Lr-oNDM6yJ!jDS^1DUpG=_c*F;<>~sPydHJs
z_BI{vaEfqp$NU9Eq~)QcS1-((>gLL8m1E~K{{VbNxl@jXm|z;O9L%op#dRBQPnJpN
zJAohUsKBceU5VstX(W?{2VjU6IqX2-RCu?IqeK&{AL4Q&+I_$oG^6m?Tgv5&Tc?&y
z(s>ebv&@P@0qu@z87_^R%pygPo=(6*kEr@nZV_RgJ(DqwV>uAq015RfM>R(A*HzQr
zz*{=B!w%~qjzYewM_;8>BAdOgzpX~snQq?u?beewmmHJI3a;J`4;=b&Q7yB_=Y>fj
z!<7!K2SLye@#|D{jSk~TU$e=3atS-)l57p*`-dItM^KUBwoTt6pdv;4#R=-f_pKi<
zJ)rbt@}6(;D&hfqVPzIG9A)1sLEL_|!@d{{gU2V{wR}sdKCR+A+n10^6}Cp1
z9+i(E+}m3t2dawXto`dV(59^$4L>rCstCtIKtD=HZOQ;vOmzfil%UBSNB4-PvD!l9
zxg)v3tc$pxcLU};U=dCSAa7PAax!|;LNRg*;~B}%0MeBs3`k-J6b0Rc4p0uK(2msX
zjBaKm=YgILN3;y(1A1;WZ3;1f0pkGV3TX)rk;(aTrHJPpsXk5MHaQvV(9(?H;ewBG
z%`mVl$KD6hm@(leQA}8b
zaRrnO=M5%EJ4a;(iuSCIQ^_n?4NlW`NH-DXd!Bj<_6hCTXLl_j1+eN{s`^)u>9Qf#
zwDmaK_Jk*%hd-ry%#U>?)RFFU4o}RWHczH|*Ui(~#ms%kkrN%f1JoYp
z>s6z(k{{lS%tYBLix42-avRju$Su-%C6a4}g@R!ekG=;z`hFC}{{Tsil(HlItga3K
z_T!4d#xs?cg~p_#@f0LY<{6d%SON0=&_05z>Qh}?L2l8sh|-2#tPz!0J*wcbmMLRt
zE`*VTo!Q*KPim*GK$1mfsEfRo89v6_T2`COOn2uVlui&?+(=o_uio;m
zRkv}EOx6jvxvx@3Hu76-kH|Y2cCbe!uzf1M#j%$8q=x3yDNtETI)=w%jMd0d)LTVr
zWMLd-zWVTbXZ5RBS2|hKErqC_8}T4BNMkG*kGGrmH`jwkV}+s;Np7kakoLR-
zj)xs;o`L8vw2x|CMA?~f^Gc^9(v|J^!tx)rIv@*k8%n2d0Od&S?N+3?w35;bSytGh
zJ7!NQfpB|ZbQPM`kx3M?B3bO6lm!yH>;sNK`_!WD^;QzOe^0%hdxdp3`E}bL${Q<>
z@v3sLxPh&wj#Xrk2^FnyS3Q1V*R@W!0^ayWR?;C9WPhX1;Nw5-cjB*FqTNqAnT$&6
zC0A*89-TeU6r7_4b{?g8ZH$p#nCA$w#JEPX`^X30G|8c!TYF?zwpj)WZ-Z{qKfT8_
zEuGE8#%Mg}iKdTd5|5i{<2lC$qn3H3K3wf0v>z;@CsJD@sP^g2B`5M4iC#!rOG!gL
znzJ^^0^2SyJFgk3Y&6S%G5p(mLb0Kb%=;N(f;eODDPfu^B#3!;VT%&Of-&rB+skl#
z=C`}Mib50!%Bfbz_p!xaG`B02bu(bn?3i2m)|zafZY||ou{iZ$4n<8Kg{RyL*%w5x
zxPiEhgE}%Ca8zcmHO5GzqEtx%X7a%#j^dXzt`>=r
z4~5KdK_uF3r13KaZTAIsp4rAK(!YkzHHeX%>*&z^5{OrH<@^K^Sgvz^#LBBr-JC
zrDP+L(BzSfjO{!h!lH)YZi{WKVfj{BZHZiQ&PUKw=V8dY8RNnp9#L#Xv${yXyxVb~
zn`k@&c;=#$!Imil+(x%*0|Z4X8B`ODk`Fkobo0!UtZ>>%1A_d*_*{(PNE~2#(dXMo
zZwR%H0rLiB6SA@AzIXzcw3Au`in+|(_z4p3SjM#5RvpD4Op%Ip%r{`$NfS(#QL$Aoa)pbN)Dhe3R;n_2
zQNXu?t^_VqQi+;5HkD}Edyp99a6Ywd{vS{F!D}Y9Xv|Y~RyJTy)K^s%wxY)Ld6E~M
zwz+$>C6loHg=t8Cv)0aQVRsy5Hm{K+Qjw9yIQ0}djA{w)d9(OFbuYH++yNns?k|QT
z1NqgPj{s|tU451*H2aAJ239c7#s}1OuHq|e%dIJ7+cHb`o$}nsip!ElPTr&GSM4n?
z#;18T<@9mg1pU)RW;RP0$?jqd6phFnOyH
z_y@!i8OlRy-)6ymv#tOmJRbGf$91MlE}sSzTthLG$rY=%*1^cz(2V0Ek>a$S?&G+=
z)0J2e8?~g0z?CDMbR*uHti#!)a6`hn$tnJe{-=W_ae(ZlZX(V9EDKt$H+4tX><_
zWg1jTGzA?MXLT|jhtr;GTG6MyyS}u%)1!HcDNrxil~KSOo7`vdr|spiawEt_gRUcF
zX&0Y&aAk~+J$R%Rej|({#SXNam;`9N+!LOI2EC3=W=Ld?c$n$-R$pnimT0ac!7Vb&y9zV>&U004uI@D(
zdy9x*yjwUW4+ha0Kmg=m^WUJNScILBqX%of4-E48IY~Bwj1+8V--_JQ{8QpBCf#lH
z?N;h25Dl@kVntEt1F69JSFTH_%{$3ur`!pyE(TpDv|y^IjmM9zQMP?X#U^nQEXuw>
z#lG}>H&p<0(D6g92CUH4J?wA`@fXFB$am{8zhEBL9uMH4)s*<7;yCf|vq
zL*>Dy#Ty1wxrCU>1bT34)P~6367Lv`$ZwTKKI;xndy~ajx}My{D2!Xk?+1{n9JvJa
zUNOhhwNsC5QbA<)aV4w(31?>B%*ZlE2W+0T*M@x3az`b5#-Ay3Xh^N+xQ*6WlsvGe
zGbud=JqC05RSiIyThEfoiE?tN{1M+H(zPds`^Lo*Vn@y)o!2L1vS!r0Ela6saVJat8zf&<}c0w^Cf?S~!+6Hn2EWAKfebMwH(>
zz0D#$ZsnCyNebJ-<105i+<$nFQ`(t5p@<1ySCJ1Y5rVp}T(R{v6wqFY(HmsT$}5rc
zIVX&P_f&POHab&FcCkN}V}t@)EPbU%?r(MG)MhBiSxX0>gmoN*PcY%%r
zE;2fU*wsd?kT@oCNp@}wuPhX#0=rc{SLFWyuaVEqE7@9D9>FW@qR-lSOFxe$yx3I0zzTeYP)Y_KuFN
zZg4U0>snFjccV@FB$pO~X(R<(dnsOd#}!&Tw2I*ESr-E<@`J{CKU%c+JDAL|ys8Ek
zM~q=jd~Y^~rOOhxo
zK2zitlma&%y*(;pZ*4NG2a4YVcJ28eLrU`IxH@-Qmm}BZnp6S6E_WvE4m~6)FF%nFK^2@!9VT14dMsbWqmnwQ1*^St})ESa1y+)|@~+LioW
zEYc&LCecca6;ej;sH2sFXz1mX+fIs2+>ed25U5p8vkd3)s`9PfjL4F#(YE6-1|V}D
zdV)IE3wW)SWe=sriQ79>*+TZC{t{sJ$r;kfl>kuUa!xyrO&q0rz0RP*Zp6|$Tx_@l
zV>Cl+41YR#ScAtLK5CfL=G$$O2@!kB;;U<0gpxnE
zO1VCBJ1O1>z!>_Po>$Z^YKyq%W@&9;lW;4Ukg3P0#W@-V5iH9apahqWC&>Q*WsPPx
zi!5RTZLR9Ge{_wdcAmZJ(s;K?4JdPZk;uO&*cfLW#T>nZLuzXl`vh{V3ut~}8#=KP
z@yF9NvFcc{7Bg5_ApkQ;70w;8>J3wW9akLuqw+Dwz7LP@UWlm#-C?o+Q#l(QcS1
zEIh}1Vp&1zN$*&wPEowp#a=s_ji^U?EWT~LWP)+JP^1CJ98=&$lstC+W1}V>FSLxQ
z^~V)nJzK+%aO)nfP%7nFpkS@)2OVlSyhEnWqB*q$#AhL1*ny8g!=8QXPF~`<&>b#o
z4LU33os3LWA1-jjo|x