Merge pull request #82 from DragonDove/master

修正中英文逗号混用,校对第二章内容
This commit is contained in:
LingCoder
2019-06-09 15:11:50 +08:00
committed by GitHub
10 changed files with 45 additions and 41 deletions

View File

@@ -5,7 +5,7 @@
这句话无论对于自然语言还是编程语言来说都是一样的。你所使用的编程语言会将你的思维模式固化并逐渐远离其他语言而且往往发生在潜移默化中。Java 作为一门傲娇的语言尤其如此。
Java 是一门派生语言,早期语言设计者为了不想在项目中使用 C++ 而创造了这种看起来很像 C++,却比 C++ 有了改进的新语言原始的项目并未成功。Java 最核心的变化就是加入了“虚拟机”和“垃圾回收机制”,这两个概念在之后的章节会有详细描述。 此外Java 还在其他方面推动了行业发展。例如,现在绝大多数编程语言都支持文档注释语法和 HTML 文档生成工具。
Java 是一门派生语言,早期语言设计者为了不想在项目中使用 C++ 而创造了这种看起来很像 C++却比 C++ 有了改进的新语言原始的项目并未成功。Java 最核心的变化就是加入了“虚拟机”和“垃圾回收机制”,这两个概念在之后的章节会有详细描述。 此外Java 还在其他方面推动了行业发展。例如,现在绝大多数编程语言都支持文档注释语法和 HTML 文档生成工具。
Java 最主要的概念之一“对象”来自 SmallTalk 语言。SmallTalk 语言恪守“对象”(在下一章中描述)是编程的最基本单元。于是,万物皆对象。历经时间的检验,人们发现这种信念太过狂热。有些人甚至认为“对象”的概念是完全错误的,应该舍弃。就我个人而言,把一切事物都抽象成对象不仅是一项不必要的负担,同时还会招致许多设计朝着不好的方向发展。尽管如此,“对象”的概念依然有其闪光点。固执地要求所有东西都是一个对象(特别是一直到最底层级别)是一种设计错误;相反,完全逃避“对象”的概念似乎同样太过苛刻。
@@ -19,7 +19,7 @@ Java 语言曾规划设计的许多功能并未按照承诺兑现。本书中,
许多语言设计决策时都考虑到了复杂性并试图降低语言的复杂性但在设计过程中遇到了一些更棘手的问题最终导致语言设计不可避免地“碰壁”复杂性增加。例如C++ 必须向后兼容 C允许 C 程序员轻松迁移),并且效率很高。这些目标非常实用,并且也是 C++ 在编程界取得了成功的原因之一但同时也引入了额外的复杂性导致某些用C++编写的项目开发失败。当然,你可以责怪程序员和管理人员手艺不精,但如果有一种编程语言可以帮助你在开发过程中发现错误,那岂不是更好?
虽然 VBVisual BASIC绑定在 BASIC 上,但 BASIC 实际上并不是一种可扩展的语言。大量扩展的堆积造成 VB 的语法难以维护。Perl 向后兼容 awk、sed、grep 以及其它要替换的 Unix 工具。因此它常常被诟病产生了一堆“只写代码”(*write-only code*,写代码的人自己都看不懂的代码。另一方面C ++VBPerl 和其他语言(如 SmallTalk在设计时重点放在了对某些复杂问题的处理上因而在解决这些特定类型的问题方面非常成功。
虽然 VBVisual BASIC绑定在 BASIC 上,但 BASIC 实际上并不是一种可扩展的语言。大量扩展的堆积造成 VB 的语法难以维护。Perl 向后兼容 awk、sed、grep 以及其它要替换的 Unix 工具。因此它常常被诟病产生了一堆“只写代码”(*write-only code*写代码的人自己都看不懂的代码。另一方面C ++VBPerl 和其他语言(如 SmallTalk在设计时重点放在了对某些复杂问题的处理上因而在解决这些特定类型的问题方面非常成功。
通信革命使我们相互沟通更加便利。无论是一对一沟通,还是团队里的互相沟通,甚至是地球上不同地区的沟通。据说下一次革命需要的是一种全球性的思维,这种思维源于足量的人以及足量相互连接。不我不知道 Java 是否能成为这场革命的工具之一,但至少这种可能性让我觉得:我现在正在做的传道授业的事情是有意义的!

View File

@@ -8,7 +8,7 @@
随着 Java 8 的出现这门语言在许多地方发生了翻天覆地的变化。在新的版本中代码的运用和实现上与以往不尽相同。这也促使了我时隔多年后再次创作了这本新书。《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才合乎逻辑的。
与几年前我们依赖印刷媒体相比YouTube博客和 StackOverflow 等网站的出现让寻找答案变得简单。请结合这些学习途径和努力坚持下去。本书可作为编程入门书籍,同时也适用于想要扩展知识的在职程序员。每次在世界各地的演讲中我都非常感谢 《*Thinking in Java*》 这本书给我带来的所有荣誉。它对于我重塑 [Reinventing Business](http://www.reinventing-business.com) 项目和促进交流是非常宝贵的。最后写这本书的原因之一 希望这本书可以为我的这个项目众筹。似乎下一步要创建一个所谓的蓝绿色组织Teal Organization才合乎逻辑的。
## 教学目标
@@ -112,7 +112,7 @@ Java 的普及性对于其受欢迎程度有重要意义。学习 Java 会让你
感谢 *Jeremy Cerise**Bill Frasure* 来到开发商务虚会预订,并随后提供了宝贵的帮助。
感谢所有花时间和精力来科罗拉多州克雷斯特德比特Crested Butte,Colorado镇参加我的研讨会开发商务聚会和其他活动的人你们的贡献可能不容易看到但却非常重要
感谢所有花时间和精力来科罗拉多州克雷斯特德比特Crested Butte, Colorado镇参加我的研讨会开发商务聚会和其他活动的人你们的贡献可能不容易看到但却非常重要

View File

@@ -13,7 +13,7 @@
## 抽象
所有编程语言都提供抽象机制。从某种程度上来说,问题的复杂度直接取决于抽象的类型和质量。这里的“类型”意思是:抽象的内容是什么?汇编语言是对底层机器的轻微抽象。接着出现的“命令式”语言(如 FORTRANBASIC 和 C是对汇编语言的抽象。与汇编相比这类语言已有了长足的改进但它们的抽象原理依然要求我们着重考虑计算机的结构而非问题本身的结构。
所有编程语言都提供抽象机制。从某种程度上来说问题的复杂度直接取决于抽象的类型和质量。这里的“类型”意思是:抽象的内容是什么?汇编语言是对底层机器的轻微抽象。接着出现的“命令式”语言(如 FORTRANBASIC 和 C是对汇编语言的抽象。与汇编相比这类语言已有了长足的改进但它们的抽象原理依然要求我们着重考虑计算机的结构而非问题本身的结构。
程序员必须要在机器模型(“解决方案空间”)和实际解决的问题模型(“问题空间”)之间建立起一种关联。这个过程既费精力,又脱离编程语言本身的范畴。这使得程序代码很难编写,维护代价高昂。同时还造就了一门副产业的“编程方法”学科。
@@ -55,7 +55,7 @@ Light lt = new Light();
lt.on();
```
在这个例子中,类型/类的名称是 **Light**,可向 **Light** 对象发出的请求包括包括打开 `on`、关闭 `off`、变得更明亮 `brighten` 或者变得更暗淡 `dim`。通过声明一个引用,`lt``new` 关键字,我们创建了一个**Light**类型的对象,再用等号将其赋给引用。
在这个例子中,类型/类的名称是 **Light**,可向 **Light** 对象发出的请求包括包括打开 `on`、关闭 `off`、变得更明亮 `brighten` 或者变得更暗淡 `dim`。通过声明一个引用`lt``new` 关键字,我们创建了一个**Light**类型的对象,再用等号将其赋给引用。
为了向对象发送消息,我们使用句点符号 `.``lt` 和消息名称 `on` 连接起来。可以看出,使用一些预先定义好的类时,我们在程序里采用的代码是非常简单直观的。
@@ -290,7 +290,7 @@ Java 的垃圾收集器被设计用来解决内存释放的问题(虽然这不
自编程语言被发明以来,程序的错误处理一直都是个难题。因为很难设计出一个好的错误处理方案,所以许多编程语言都忽略了这个问题,把这个问题丢给了程序类库的设计者。他们提出了在许多情况下都可以工作但很容易被规避的半途而废的措施,通常只需忽略错误。多数错误处理方案的主要问题是:它们依赖程序员之间的约定俗成而不是语言层面的限制。换句话说,如果程序员赶时间或没想起来,这些方案就很容易被忘记。
异常处理机制将程序错误直接交给编程语言甚至是操作系统。“异常”Exception是一个从出错点“抛出”thrown后能被特定类型的异常处理程序捕获(catch)的一个对象。它不会干扰程序的正常运行,仅当程序出错的时候才被执行。这让我们的编码更简单:不用再反复检查错误了。另外,异常不像方法返回的错误值和方法设置用来表示发生错误的标志位那样可以被忽略。异常的发生是不会被忽略的,它终究会在某一时刻被处理。
异常处理机制将程序错误直接交给编程语言甚至是操作系统。“异常”Exception是一个从出错点“抛出”thrown后能被特定类型的异常处理程序捕获(catch)的一个对象。它不会干扰程序的正常运行,仅当程序出错的时候才被执行。这让我们的编码更简单:不用再反复检查错误了。另外,异常不像方法返回的错误值和方法设置用来表示发生错误的标志位那样可以被忽略。异常的发生是不会被忽略的它终究会在某一时刻被处理。
最后,“异常机制”提供了一种可靠地从错误状况中恢复的方法,使得我们可以编写出更健壮的程序。有时你只要处理好抛出的异常情况并恢复程序的运行即可,无需退出。

View File

@@ -4,16 +4,16 @@
现在,我们来为这次阅读之旅做些准备吧!
在开始学习 Java 之前,你必须要先安装好 Java 和本书的源代码示例。因为考虑到可能有“专门的初学者”从本书开始学习编程,所以我会仔细解释计算机命令行 Shell 的这个过程。 如果你已经有此方面的经验了,可以跳过这段安装说明。如果你对此处描述的任何术语或过程仍不清楚,还可以通过 Google 搜索找到答案。具体的问题或困难请试着在 StackOverflow 上提问。或者去 YouTube 看有没有相关的安装说明。
在开始学习 Java 之前,你必须要先安装好 Java 和本书的源代码示例。因为考虑到可能有“专门的初学者”从本书开始学习编程,所以我会详细地教你如何使用命令行。 如果你已经有此方面的经验了,可以跳过这段安装说明。如果你对此处描述的任何术语或过程仍不清楚,还可以通过 [Google](https://google.com/) 搜索找到答案。具体的问题或困难请试着在 [StackOverflow](https://stackoverflow.com/) 上提问。或者去 [YouTube](https://youtube.com) 看有没有相关的安装说明。
## 编辑器
首先你需要安装一个编辑器来创建和修改本书用例里的 Java 代码。有可能你还需要一个编辑器来更改系统配置文件。
首先你需要安装一个编辑器来创建和修改本书用例里的 Java 代码。有可能你还需要使用编辑器来更改系统配置文件。
相比一些重量级的 IDEIntegrated Development Environments开发集成环境)软件如Eclipse、NetBeans和IntelliJ IDEA (译者注做项目强烈推荐IDEA),编辑器是一种基础的运行程序的文本编辑器。如果你已经有了一个 IDE 用着还顺手,那就可以直接用了。为了方便后面的学习和统一下教学环境,我推荐大家使用 Atom 这个编辑器。大家可以在 [atom.io](http://atom.io) 网站下载。
相比一些重量级的 IDEIntegrated Development Environments集成开发环境如Eclipse、NetBeans和IntelliJ IDEA (译者注做项目强烈推荐IDEA),编辑器是一种更纯粹的文本编辑器。如果你已经有了一个用着顺手的 IDE,那就可以直接用了。为了方便后面的学习和统一下教学环境,我推荐大家使用 Atom 这个编辑器。大家可以在 [atom.io](https://atom.io) 下载。
Atom 是一个免费开源、易于安装且跨平台(支持 Window、Mac和Linux的文本编辑器。内置支持 Java 文件。相比 IDE 的厚重,比较轻量级是学习本书的理想工具。Atom 包含了许多方便的编辑功能,相信你一定会爱上!更多关于 Atom 使用的细节问题可以到她们的网站上。
Atom 是一个免费开源、易于安装且跨平台(支持 Window、Mac和Linux的文本编辑器。内置支持 Java 文件。相比 IDE 的厚重,比较轻量级是学习本书的理想工具。Atom 包含了许多方便的编辑功能相信你一定会爱上!更多关于 Atom 使用的细节问题可以到的网站上寻找
还有很多其他的编辑器。有一种亚文化的群体,他们热衷于争论哪个更好用!如果你找到一个你更喜欢的编辑器,换一种使用也没什么难度。重要的是,你要找一个用着舒服的。
@@ -26,15 +26,18 @@
Mac单击聚光灯屏幕右上角的放大镜图标然后键入 `terminal`。单击看起来像小电视屏幕的应用程序你也可以单击“return”。这就启动了你的用户下的 shell 窗口。
windows首先通过目录打开 windows 资源管理器:
Windows 7: 单击屏幕左下角的“开始”图标输入“explorer”后按回车键。
Windows 8: 按 Windows+Q, 输入 “explorer” 后按回车键。
Windows 10: 按 Windows+E 打开资源管理器,导航到所需目录,单击窗口左上角的“文件“选项卡,选择“打开 Window PowerShell”启动 Shell
Linux: 在 home 目录打开 Shell。
Debian: 按 Alt+F2 在弹出的对话框中输入“gnome-terminal”
Ubuntu: 在屏幕中鼠标右击,选择 “打开终端”, 或者按住 Ctrl+Alt+T
Redhat: 在屏幕中鼠标右击,选择 “打开终端”
Fedora: 按 Alt+F2在弹出的对话框中输入“gnome-terminal”
windows首先通过目录打开 windows 资源管理器:
- Windows 7: 单击屏幕左下角的“开始”图标,输入“explorer”后按回车键。
- Windows 8: 按 Windows+Q输入 “explorer” 后按回车键
- Windows 10: 按 Windows+E 打开资源管理器,导航到所需目录,单击窗口左上角的“文件“选项卡,选择“打开 Window PowerShell”启动 Shell。
Linux: 在 home 目录打开 Shell。
- Debian: 按 Alt+F2 在弹出的对话框中输入“gnome-terminal”
- Ubuntu: 在屏幕中鼠标右击,选择 “打开终端”,或者按住 Ctrl+Alt+T
- Redhat: 在屏幕中鼠标右击,选择 “打开终端”
- Fedora: 按 Alt+F2在弹出的对话框中输入“gnome-terminal”
**目录**
@@ -47,7 +50,7 @@ Mac单击聚光灯屏幕右上角的放大镜图标然后键入 `ter
```bash
更改目录: cd <路径>
cd .. 移动到上级目录
pushd <路径> 记住来源的同时移动到其他目录,popd 返回来源
pushd <路径> 记住来源的同时移动到其他目录popd 返回来源
目录列举: ls 列举出当前目录下所有的文件和子目录名(不包含隐藏文件),
可以选择使用通配符 * 来缩小搜索范围。
@@ -80,8 +83,8 @@ Mac单击聚光灯屏幕右上角的放大镜图标然后键入 `ter
Windows 系统:按 F7 键
文件解压:
Linux/Mac 都有命令行解压程序unzip你可以通过互联网为Windows安装命令行解压程序unzip。
图形界面下Windows 资源管理器Mac Finder Linux Nautilus 或其他等效软件)右键单击该文件,
Linux/Mac 都有命令行解压程序 unzip你可以通过互联网为 Windows 安装命令行解压程序 unzip。
图形界面下Windows 资源管理器Mac FinderLinux Nautilus 或其他等效软件)右键单击该文件,
在 Mac 上选择“open”在 Linux 上选择“extract here”或在 Windows 上选择“extract all…”。
要了解关于 shell 的更多信息,请在维基百科中搜索 Windows shellMac/Linux用户可搜索 bash shell。
@@ -90,7 +93,7 @@ Mac单击聚光灯屏幕右上角的放大镜图标然后键入 `ter
## Java安装
为了编译和运行代码示例,首先你必须安装 JDK。本书中采用的是 JDK 8版本。(注JDK 全称是 Java Development Kit是用于支持Java程序开发的最小环境)
为了编译和运行代码示例,首先你必须安装 JDKJava Development KitJAVA 软件开发工具包)。本书中采用的是 JDK 8。
**Windows**
@@ -105,6 +108,7 @@ Mac单击聚光灯屏幕右上角的放大镜图标然后键入 `ter
**Macintosh**
Mac 系统自带的 Java 版本太老,为了确保本书的代码示例能被正确执行,你必须将它先更新到 Java 8。我们需要管理员权限来运行下面的步骤
1. 以下为 HomeBrew 的[安装说明](https://brew.sh/)。安装完成后执行命令 `brew update` 更新到最新版本
2. 在命令行下执行下面的命令来安装 Java。
@@ -153,7 +157,7 @@ Java HotSpot(TM) 64-Bit Server VM (build 25.112-b15, mixed mode)
1. 从 [GitHub 仓库](https://github.com/BruceEckel/OnJava8-Examples/archive/master.zip)中下载本书代码示例
2. 解压到你所选目录里。
3. 使用 Windows 资源管理器, Mac Finder, or Linux 的 Nautilus 或其他等效工具浏览,在该目录下打开 Shell。
3. 使用 Windows 资源管理器Mac FinderLinux 的 Nautilus 或其他等效工具浏览,在该目录下打开 Shell。
4. 如果你在正确的目录中,你应该看到该目录中名为 gradlew 和 gradlew.bat 的文件,以及许多其他文件和目录。目录与书中的章节相对应。
5. 在shell中输入下面的命令运行
@@ -171,7 +175,7 @@ Java HotSpot(TM) 64-Bit Server VM (build 25.112-b15, mixed mode)
**Gradle基础任务**
本书构建的大量 Gradle 任务都可以自动运行。Gradle 使用约定大于配置的方式,简单设置即可具备高可用性。本书中“一起去骑行”的某些任务不适用于此或无法执行成功。以下是你通常会使用上的分级任务列表:
本书构建的大量 Gradle 任务都可以自动运行。Gradle 使用约定大于配置的方式,简单设置即可具备高可用性。本书中“一起去骑行”的某些任务不适用于此或无法执行成功。以下是你通常会使用上的 Gradle 任务列表:
```bash
编译本书中的所有 java 文件,除了部分错误示范的

View File

@@ -47,7 +47,7 @@ Java 语法允许我们使用带双引号的文本内容来初始化字符串。
### 数据存储
那么, 程序在运行时是如何存储的呢尤其是内存是怎么分配的。有5个不同的地方可以存储数据
那么程序在运行时是如何存储的呢尤其是内存是怎么分配的。有5个不同的地方可以存储数据
1. **寄存器** Registers 最快的存储区域位于CPU内部 [^2]。然而寄存器的数量十分有限所以寄存器根据需求进行分配。我们对其没有直接的控制权也无法在自己的程序里找到寄存器存在的踪迹另一方面C/C++ 允许开发者向编译器建议寄存器的分配)。

View File

@@ -261,7 +261,7 @@ x = a * (-b);
## 递增和递减
和 C 语言类似Java 提供了许多快捷运算方式。快捷运算可使代码可读性,可写性都更强。其中包括递增 `++` 和递减 `--`,意为“增加或减少一个单位”。举个例子来说,假设 a 是一个 **int** 类型的值,则表达式 `++a` 就等价于 `a = a + 1`。 递增和递减运算符不仅可以修改变量,还可以生成变量的值。
和 C 语言类似Java 提供了许多快捷运算方式。快捷运算可使代码可读性可写性都更强。其中包括递增 `++` 和递减 `--`意为“增加或减少一个单位”。举个例子来说,假设 a 是一个 **int** 类型的值,则表达式 `++a` 就等价于 `a = a + 1`。 递增和递减运算符不仅可以修改变量,还可以生成变量的值。
每种类型的运算符,都有两个版本可供选用;通常将其称为“前缀”和“后缀”。“前递增”表示 `++` 运算符位于变量或表达式的前面;而“后递增”表示 `++` 运算符位于变量的后面。类似地,“前递减”意味着 `--` 运算符位于变量的前面;而“后递减”意味着 `--` 运算符位于变量的后面。对于前递增和前递减(如 `++a` 或 `--a`),会先执行递增/减运算,再返回值。而对于后递增和后递减(如 `a++` 或 `a--`),会先返回值,再执行递增/减运算。代码示例:
@@ -486,7 +486,7 @@ expression is false
test10&& test22&& test32
```
可能你的预期是程序会执行 3 个 **test** 方法并返回。我们来分析一下:第一个方法的结果返回 `true`,因此表达式会继续走下去。紧接着,第二个方法的返回结果是 `false`。这就代表这整个表达式的结果肯定为 `false`,所以就没有必要再判断剩下的表达式部分了。
可能你的预期是程序会执行 3 个 **test** 方法并返回。我们来分析一下:第一个方法的结果返回 `true`因此表达式会继续走下去。紧接着,第二个方法的返回结果是 `false`。这就代表这整个表达式的结果肯定为 `false`,所以就没有必要再判断剩下的表达式部分了。
所以,运用“短路”可以节省部分不必要的运算,从而提高程序潜在的性能。
@@ -1474,7 +1474,7 @@ public class AllOps {
**注意** **boolean** 类型的的运算是受限的。你能为其赋值 `true` 或 `false`,也可测试它的值是否是 `true` 或 `false`。但你不能对其作加减等其他运算。
在 **char** , **byte** 和 **short** 类型中,我们可以看到算术运算符的“类型转换”效果。我们必须要显式强制类型转换才能将结果重新赋值为原始类型。对于 **int** 类型的运算则不用转换,因为默认就是 **int** 型。虽然我们不用再停下来思考这一切是否安全,但是两个大的 int 型整数相乘时,结果有可能超出 **int** 型的范围,这种情况下结果会发生溢出。下面的代码示例:
在 **char****byte** 和 **short** 类型中,我们可以看到算术运算符的“类型转换”效果。我们必须要显式强制类型转换才能将结果重新赋值为原始类型。对于 **int** 类型的运算则不用转换,因为默认就是 **int** 型。虽然我们不用再停下来思考这一切是否安全,但是两个大的 int 型整数相乘时,结果有可能超出 **int** 型的范围,这种情况下结果会发生溢出。下面的代码示例:
```java
// operators/Overflow.java
@@ -1508,7 +1508,7 @@ bigger = -4
[^1]: 我在 *Pomona College* 大学读过两年本科,在那里 47 被称之为“魔法数字”(*magic number*),详见 [维基百科](https://en.wikipedia.org/wiki/47_(number)) 。
[^2]: *John Kirkham* 说过, “自 1960 年我开始在 IBM 1620 上开始编程起,至 1970 年之间FORTRAN 一直都是一种全大写的编程语言。这可能是因为许多早期的输入设备都是旧的电传打字机使用了5 位波特码,没有小写字母的功能。指数符号中的 e 也总是大写的,并且从未与自然对数底数 e 混淆,自然对数底数 e 总是小写的。 e 简单地代表指数,通常 10 是基数。那时,八进制也被程序员广泛使用。虽然我从未见过它的用法,但如果我看到一个指数符号的八进制数,我会认为它是以 8 为基数的。我记得第一次看到指数使用小写字母 e 是在 20 世纪 70 年代末,我也发现它令人困惑。这个问题出现的时候,小写字母悄悄进入了 Fortran。如果你真的想使用自然对数底我们实际上有一些函数要使用但是它们都是大写的。
[^2]: *John Kirkham* 说过“自 1960 年我开始在 IBM 1620 上开始编程起,至 1970 年之间FORTRAN 一直都是一种全大写的编程语言。这可能是因为许多早期的输入设备都是旧的电传打字机使用了5 位波特码,没有小写字母的功能。指数符号中的 e 也总是大写的,并且从未与自然对数底数 e 混淆,自然对数底数 e 总是小写的。 e 简单地代表指数,通常 10 是基数。那时,八进制也被程序员广泛使用。虽然我从未见过它的用法,但如果我看到一个指数符号的八进制数,我会认为它是以 8 为基数的。我记得第一次看到指数使用小写字母 e 是在 20 世纪 70 年代末,我也发现它令人困惑。这个问题出现的时候,小写字母悄悄进入了 Fortran。如果你真的想使用自然对数底我们实际上有一些函数要使用但是它们都是大写的。
<!-- 分页 -->

View File

@@ -4,7 +4,7 @@
> 程序必须在执行过程中控制它的世界并做出选择。 在 Java 中,你需要执行控制语句来做出选择。
Java 使用了 C 的所有执行控制语句,因此对于熟悉 C/C++ 编程的人来说,这部分内容轻车熟路。大多数面向过程编程语言都有共通的某种控制语句。在 Java 中,涉及的关键字包括 **if-elsewhiledo-whileforreturnbreak** 和选择语句 **switch**。 Java 并不支持备受诟病的 **goto**(尽管它在某些特殊场景中依然是最行之有效的方法)。 尽管如此,在 Java 中我们仍旧可以进行类似的逻辑跳转,但较之典型的 **goto** 用法限制更多。
Java 使用了 C 的所有执行控制语句,因此对于熟悉 C/C++ 编程的人来说,这部分内容轻车熟路。大多数面向过程编程语言都有共通的某种控制语句。在 Java 中,涉及的关键字包括 **if-elsewhiledo-whileforreturnbreak** 和选择语句 **switch**。 Java 并不支持备受诟病的 **goto**(尽管它在某些特殊场景中依然是最行之有效的方法)。 尽管如此,在 Java 中我们仍旧可以进行类似的逻辑跳转但较之典型的 **goto** 用法限制更多。
## true和flase

View File

@@ -370,7 +370,7 @@ Help!
**[5]** `assist()` 是静态内部类中的静态方法。
**[6]** 我们将 **Describe** 对象的方法引用赋值给 **Callable** , 它没有 `show()` 方法,而是 `call()` 方法。 但是Java 似乎接受用这个看似奇怪的赋值,因为方法引用符合 **Callable**`call()` 方法的签名。
**[6]** 我们将 **Describe** 对象的方法引用赋值给 **Callable** 它没有 `show()` 方法,而是 `call()` 方法。 但是Java 似乎接受用这个看似奇怪的赋值,因为方法引用符合 **Callable**`call()` 方法的签名。
**[7]** 我们现在可以通过调用 `call()` 来调用 `show()`,因为 Java 将 `call()` 映射到 `show()`

View File

@@ -87,7 +87,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。最后一种类型通常意味着收集流元素通常是到集合中
下面我们来看下每种类型的流操作。
@@ -769,7 +769,7 @@ Well WELL well it IT it s S s so SO so
### 流元素排序
`Randoms.java`,我们熟识了 `sorted()` 的默认比较器实现。其实它还有另一种形式的实现:传入一个 **Comparator** 参数。代码示例:
`Randoms.java`我们熟识了 `sorted()` 的默认比较器实现。其实它还有另一种形式的实现:传入一个 **Comparator** 参数。代码示例:
```java
// streams/SortedComparator.java
@@ -1357,7 +1357,7 @@ Null
- `map(Function)`:如果 **Optional** 不为空,则将 **Function** 应用于 **Optional** 的内容,并将结果返回。否则,直接返回 **Optional.empty**
- `flatMap(Function)`:如同 `map()` 但是提供的映射函数将结果包装在 **Optional** 对象中,因此 `flatMap()` 不会在最后进行任何包装。
如上方法都不适用于数值型 **Optional**。普通流过滤器会在 **Predicate** 返回 false 时删除流元素。`Optional.filter()`**Predicate** 失败时不会删除 **Optional**——而是把它留保留下来, 但将其转化为空:
如上方法都不适用于数值型 **Optional**。普通流过滤器会在 **Predicate** 返回 false 时删除流元素。`Optional.filter()`**Predicate** 失败时不会删除 **Optional**——而是把它留保留下来但将其转化为空:
```java
// streams/OptionalFilter.java
@@ -1835,11 +1835,11 @@ public class MapCollector {
{688=W, 309=C, 293=B, 761=N, 858=N, 668=G, 622=F, 751=N}
```
**Pair** 只是一个基础的数据对象。**RandomPair** 创建了随机生成的 **Pair** 对象流。如果我们能以某种方式组合两个流, 那就再好不过了, 但 Java 在这个问题上与我们斗争。所以我创建了一个整数流,并且使用 `mapToObj()` 将其转化成为 **Pair** 流。 **capChars** 随机生成的大写字母迭代器从流开始,然后 `iterator()` 方法允许我们在 `stream()` 方法中使用它。就我所知, 这是组合多个流以生成新的对象流的唯一方法。
**Pair** 只是一个基础的数据对象。**RandomPair** 创建了随机生成的 **Pair** 对象流。如果我们能以某种方式组合两个流那就再好不过了但 Java 在这个问题上与我们斗争。所以我创建了一个整数流,并且使用 `mapToObj()` 将其转化成为 **Pair** 流。 **capChars** 随机生成的大写字母迭代器从流开始,然后 `iterator()` 方法允许我们在 `stream()` 方法中使用它。就我所知这是组合多个流以生成新的对象流的唯一方法。
在这里,我们只使用最简单形式的 `Collectors.toMap()`,这个方法值需要一个可以从流中获取键值对的函数。还有其他重载形式,其中一种形式是在遇到键值冲突时,需要一个函数来处理这种情况。
在大多数情况下,你可以在 `java.util.stream.Collectors`寻找到你想要的预先定义好的 **Collector**。在少数情况下当你找不到想要的时候,你可以使用第二种形式的 ` collect()`。 我基本上把它留作更高级的练习, 但是这里有一个例子给出了基本想法:
在大多数情况下,你可以在 `java.util.stream.Collectors`寻找到你想要的预先定义好的 **Collector**。在少数情况下当你找不到想要的时候,你可以使用第二种形式的 ` collect()`。 我基本上把它留作更高级的练习但是这里有一个例子给出了基本想法:
```java
// streams/SpecialCollector.java
@@ -1933,7 +1933,7 @@ Lambda 表达式中的第一个参数 `fr0` 是上一次调用 `reduce()` 的结
- `anyMatch(Predicate)`:如果流中的一个元素根据提供的 **Predicate** 返回 true 时,结果返回为 true。这个操作将会在第一个 true 之后短路;也就是不会在发生 true 之后继续执行计算。
- `noneMatch(Predicate)`:如果流的每个元素根据提供的 **Predicate** 都返回 false 时,结果返回为 true。这个操作将会在第一个 true 之后短路;也就是不会在发生 true 之后继续执行计算。
你已经在 `Prime.java` 中看到了 `noneMatch()` 的示例;` allMatch()``anyMatch()` 的用法基本上是等同的。让我们探究短路行为。为了创建消除冗余代码的 ` show()` 方法,我们必须首先发现如何概括地描述所有三个匹配器操作, 然后将其转换为称为 **Matcher** 的接口:
你已经在 `Prime.java` 中看到了 `noneMatch()` 的示例;` allMatch()``anyMatch()` 的用法基本上是等同的。让我们探究短路行为。为了创建消除冗余代码的 ` show()` 方法,我们必须首先发现如何概括地描述所有三个匹配器操作然后将其转换为称为 **Matcher** 的接口:
```java
// streams/Matching.java
@@ -2086,7 +2086,7 @@ you
- `average()` :求取流元素平均值。
- `max()``min()`:因为这些操作在数字流上面,所以不需要 **Comparator**
- `sum()`:对所有流元素进行求和。
- `summaryStatistics()`:生成可能有用的数据。目前还不太清楚他们为什么觉得有必要这样做, 但是你可以直接使用方法产生所有的数据。
- `summaryStatistics()`:生成可能有用的数据。目前还不太清楚他们为什么觉得有必要这样做但是你可以直接使用方法产生所有的数据。
```java
// streams/NumericStreamInfo.java

View File

@@ -119,7 +119,7 @@ true
我已经在这一章第一个程序的**main()**方法添加了第一行用于展示操作系统的名称,因此你可以看到不同操作系统之间存在哪些差异。理想情况下,差别会相对较小,并且使用**/**或者**\\**路径分隔符进行分隔。你可以看到我运行在Windows 10上的程序输出。
当**toString()**方法生成完整形式的路径,你可以看到**getFileName()** 方法总是返回当前文件名。
通过使用**Files**工具类(我们接下类将会更多的使用它),可以测试一个文件是否存在,测试是否是一个"真正"的文件还是一个目录等等。"Nofile.txt"这个示例展示我们描述的文件可能并不在指定的位置;这样可以允许你创建一个新的路径。"PathInfo.java"存在于当前目录中,最初它只是没有路径的文件名,但它仍然被检测为"存在"。一旦我们将其转换为绝对路径,我们将会得到一个从"C:"盘(因为我们是在Windows机器下进行测试)开始的完整路径,现在它也拥有一个父路径。“真实”路径的定义在文档中有点模糊,因为它取决于具体的文件系统。例如,如果文件名不区分大小写,即使路径由于大小写的缘故而不是完全相同,也可能得到肯定的匹配结果。在这样的平台上,**toRealPath()** 将返回实际情况下的**Path**,并且还会删除任何冗余元素。
通过使用**Files**工具类(我们接下类将会更多的使用它),可以测试一个文件是否存在,测试是否是一个"真正"的文件还是一个目录等等。"Nofile.txt"这个示例展示我们描述的文件可能并不在指定的位置;这样可以允许你创建一个新的路径。"PathInfo.java"存在于当前目录中,最初它只是没有路径的文件名,但它仍然被检测为"存在"。一旦我们将其转换为绝对路径,我们将会得到一个从"C:"盘(因为我们是在Windows机器下进行测试)开始的完整路径,现在它也拥有一个父路径。“真实”路径的定义在文档中有点模糊因为它取决于具体的文件系统。例如,如果文件名不区分大小写,即使路径由于大小写的缘故而不是完全相同,也可能得到肯定的匹配结果。在这样的平台上,**toRealPath()** 将返回实际情况下的**Path**,并且还会删除任何冗余元素。
这里你会看到**URI**看起来只能用于描述文件,实际上**URI**可以用于描述更多的东西;通过[维基百科]()可以了解更多细节。现在我们成功地将**URI**转为一个**Path**对象。