@@ -48,7 +48,7 @@ String x = Immutable.upcase(s);
4848## ` + ` 的重载与` StringBuilder `
4949` String ` 对象是不可变的,你可以给一个` String ` 对象添加任意多的别名。因为` String ` 是只读的,所以指向它的任何引用都不可能改它的值,因此,也就不会影响到其他引用。
5050
51- 不可变性会带来一定的效率问题。为` String ` 对象重载的` + ` 操作符就是一个例子。重载的意思是,一个操作符在用于特定的类时,被赋予了特殊的意义(用于` String ` 的` + ` 与` += ` 是Java中仅有的两个重载过的操作符,Java不允许程序员重载任何其他的操作符[ ^ 1 ] )。
51+ 不可变性会带来一定的效率问题。为` String ` 对象重载的` + ` 操作符就是一个例子。重载的意思是,一个操作符在用于特定的类时,被赋予了特殊的意义(用于` String ` 的` + ` 与` += ` 是Java中仅有的两个重载过的操作符,Java不允许程序员重载任何其他的操作符 [ ^ 1 ] )。
5252
5353操作符` + ` 可以用来连接` String ` :
5454``` java
@@ -469,7 +469,6 @@ Total 49.39
469469正如你所见,通过相当简洁的语法,`Formatter `提供了对空格与对齐的强大控制能力。在该程序中,为了恰当地控制间隔,格式化字符串被重复利用了多遍。
470470### `Formatter `转换
471471下面的表格展示了最常用的类型转换:
472- <<<<<< < HEAD
473472| 类型 | 含义 |
474473| : ---- : | ---- |
475474| `d` | 整型(十进制)|
@@ -482,19 +481,6 @@ Total 49.39
482481| `h` | 散列码(十六进制)|
483482| `% ` | 字面值“% ”|
484483下面的程序演示了这些转换是如何工作的:
485- ====== =
486- | -- - | -- - |
487- | ** `d`** | ** 整型(十进制)** |
488- | ** `c`** | ** Unicode 字符** |
489- | ** `b`** | ** Boolean 值** |
490- | ** `s`** | ** String ** |
491- | ** `f`** | ** 浮点数(十进制)** |
492- | ** `e`** | ** 浮点数(科学计数)** |
493- | ** `x`** | ** 整型(十六进制)** |
494- | ** `h`** | ** 散列码(十六进制)** |
495- | ** `% `** | ** 字符“% ”** |
496- 下面的程序演示了这些转换时如何工作的:
497- >>>>>> > beacc51a2ed07e07e476d69a2b4c1602e5b5ff4e
498484```java
499485// strings/Conversion.java
500486import java. math. * ;
@@ -693,7 +679,7 @@ public class Hex {
693679```java
694680- ?
695681```
696- 要描述一个整数,你可以说它有一位或多位阿拉伯数字。在正则表达式中,用`\d`表示一位数字。如果在其他语言中使用过正则表达式,那你可能就能发现Java 对反斜线\的不同处理方式。在其他语言中,`\\`表示“我想要在正则表达式中插入一个普通的(字面上的)反斜线,请不要给它任何特殊的意义。”而在Java 中,`\\`的意思是“我要插入一个正则表达式的反斜线,所以其后的字符具有特殊的意义。”例如,如果你想表示一位数字,那么正则表达式因该是`\\d`。如果你想插入一个普通的反斜线,应该这样写`\\\`。不过换行符和制表符之类的东西只需要使用单反斜线:`\n\t`。
682+ 要描述一个整数,你可以说它有一位或多位阿拉伯数字。在正则表达式中,用`\d`表示一位数字。如果在其他语言中使用过正则表达式,那你可能就能发现Java 对反斜线\的不同处理方式。在其他语言中,`\\`表示“我想要在正则表达式中插入一个普通的(字面上的)反斜线,请不要给它任何特殊的意义。”而在Java 中,`\\`的意思是“我要插入一个正则表达式的反斜线,所以其后的字符具有特殊的意义。”例如,如果你想表示一位数字,那么正则表达式因该是`\\d`。如果你想插入一个普通的反斜线,应该这样写`\\\`。不过换行符和制表符之类的东西只需要使用单反斜线:`\n\t`。 [ ^ 2 ]
697683
698684要表示“一个或多个之前的表达式”,应该使用`+ `。所以,如果要表示“可能有一个负号,后面跟着一位或多位数字”,可以这样:
699685```java
@@ -789,7 +775,7 @@ the mightiest banana in the forest...with... a banana!
789775稍后你会看到,`String `之外的正则表达式还有更强大的替换工具,例如,可以通过方法调用执行替换。而且,如果正则表达式不是只使用一次的话,非`String `对象的正则表达式明显具备更佳的性能。
790776### 创建正则表达式
791777我们首先从正则表达式可能存在的构造集中选取一个很有用的子集,以此开始学习正则表达式。正则表达式的完整构造子列表,请参考JDK 文档`java. util. regex`包中的`Pattern `类。
792- <<<<<< < HEAD
778+
793779| 表达式 | 含义 |
794780| : ---- | : ---- |
795781| `B ` | 指定字符`B ` |
@@ -801,18 +787,6 @@ the mightiest banana in the forest...with... a banana!
801787| `\f` | 换页 |
802788| `\e` | 转义(Escape ) |
803789
804- ====== =
805- | | |
806- | ---- | ---- |
807- | ** `B `** | ** 指定字符`B `** |
808- | ** `\xhh`** | ** 十六进制值为`0xhh`的字符** |
809- | ** `\uhhhh`** | ** 十六进制表现为`0xhhhh`的Unicode 字符** |
810- | ** `\t`** | ** 制表符Tab ** |
811- | ** `\n`** | ** 换行符** |
812- | ** `\r`** | ** 回车** |
813- | ** `\f`** | ** 换页** |
814- | ** `\e`** | ** 转义Escape ** |
815- >>>>>> > beacc51a2ed07e07e476d69a2b4c1602e5b5ff4e
816790当你学会了使用字符类(character classes)之后,正则表达式的威力才能真正显现出来。以下是一些创建字符类的典型方式,以及一些预定义的类:
817791
818792| 表达式 | 含义 |
@@ -914,7 +888,7 @@ interface CharSequence {
914888### `Pattern `和`Matcher `
915889通常,比起功能有限的`String `类,我们更愿意构造功能强大的正则表达式对象。只需导入`java. util. regex`包,然后用`static Pattern . compile()`方法来编译你的正则表达式即可。它会根据你的`String `类型的正则表达式生成一个`Pattern `对象。接下来,把你想要检索的字符串传入`Pattern `对象的`matcher()`方法。`matcher()`方法会生成一个`Matcher `对象,它有很多功能可用(可以参考`java.util.regext. Matcher `的JDK 文档)。例如,它的`replaceAll()`方法能将所有匹配的部分都替换成你传入的参数。
916890
917- 作为第一个示例,下面的类可以用来测试正则表达式,看看它们能否匹配一个输入字符串。第一个控制台参数是将要用来搜索匹配的输入字符串,后面的一个或多个参数都是正则表达式,它们将被用来在输入的第一个字符串中查找匹配。在Unix / Linux 上,命令行中的正则表达式必须用引号括起来。这个程序在测试正则表达式时很有用,特别是当你想验证它们是否具备你所期待的匹配功能的时候。
891+ 作为第一个示例,下面的类可以用来测试正则表达式,看看它们能否匹配一个输入字符串。第一个控制台参数是将要用来搜索匹配的输入字符串,后面的一个或多个参数都是正则表达式,它们将被用来在输入的第一个字符串中查找匹配。在Unix / Linux 上,命令行中的正则表达式必须用引号括起来。这个程序在测试正则表达式时很有用,特别是当你想验证它们是否具备你所期待的匹配功能的时候。[ ^ 3 ]
918892```java
919893// strings/TestRegularExpression.java
920894// Simple regular expression demonstration
@@ -1059,7 +1033,7 @@ Bandersnatch.][frumious][Bandersnatch.]
10591033```
10601034这首诗来自于Lewis Carroll 所写的* Through the Looking Glass * 中的“Jabberwocky ”。可以看到这个正则表达式模式有许多圆括号分组,由任意数目的非空白符(`\\S + `)及随后的任意数目的空白符(`\\s+ `)所组成。目的是捕获每行的最后3 个词,每行最后以`\$`结束。不过,在正常情况下是将`\$`与整个输入序列的末端相匹配。所以我们一定要显示地告知正则表达式注意输入序列中的换行符。这可以由序列开头的模式标记`(? m)`来完成(模式标记马上就会介绍)。
10611035### `start()`和`end()`
1062- 在匹配操作成功之后,`start()`返回先前匹配的起始位置的索引,而`end()`返回所匹配的最后字符的索引加一的值。匹配操作失败之后(或先于一个正在进行的匹配操作去尝试)调用`start()`或`end()`将会产生`IllegalStateException `。下面的示例还同时展示了`matches()`和`lookingAt()`的用法[^ 4 ]:
1036+ 在匹配操作成功之后,`start()`返回先前匹配的起始位置的索引,而`end()`返回所匹配的最后字符的索引加一的值。匹配操作失败之后(或先于一个正在进行的匹配操作去尝试)调用`start()`或`end()`将会产生`IllegalStateException `。下面的示例还同时展示了`matches()`和`lookingAt()`的用法 [^ 4 ]:
10631037```java
10641038// strings/StartEnd.java
10651039import java. util. regex. * ;
@@ -1139,7 +1113,7 @@ lookingAt() start = 0 end = 14
11391113matches() start = 0 end = 31
11401114*/
11411115```
1142- 注意,`find()`可以在输入的任意位置定位正则表达式,而`lookingAt()`和`matches()`只有在正则表达式与输入的最开始处就开始匹配时才会成功。`matches()`只有在整个输入都匹配正则表达式时才会成功,而`lookingAt()`[^ 5 ]只要输入的第一部分匹配就会成功。
1116+ 注意,`find()`可以在输入的任意位置定位正则表达式,而`lookingAt()`和`matches()`只有在正则表达式与输入的最开始处就开始匹配时才会成功。`matches()`只有在整个输入都匹配正则表达式时才会成功,而`lookingAt()` [^ 5 ]只要输入的第一部分匹配就会成功。
11431117### `Pattern `标记
11441118`Pattern `类的`compile()`方法还有另一个版本,它接受一个标记参数,以调整匹配行为:
11451119```java
@@ -1531,23 +1505,23 @@ But I'm not dead yet! I feel happy!
15311505But I'm not dead yet! I feel happy!
15321506*/
15331507```
1534- 使用正则表达式或`Scanner `对象,我们能够以更加复杂的模式来分割一个字符串,而这对于`StringTokenizer `来说就很困难了。基本上,我们可以放心地说,`StringTokenizer `已经可以废弃不用了[^ 2 ]。
1508+ 使用正则表达式或`Scanner `对象,我们能够以更加复杂的模式来分割一个字符串,而这对于`StringTokenizer `来说就很困难了。基本上,我们可以放心地说,`StringTokenizer `已经可以废弃不用了 [^ 2 ]。
15351509
15361510
15371511< ! -- Summary -- >
15381512## 本章小结
15391513过去,Java 对于字符串操作的技术相当不完善。不过随着近几个版本的升级,我们可以看到,Java 已经从其他语言中吸取了许多成熟的经验。到目前为止,它对字符串操作的支持已经很完善了。不过,有时你还要在细节上注意效率问题,例如恰当地使用`StringBuilder `等。
15401514
15411515
1542- [^ 1 ]: C ++ 允许编程人员任意重载操作符。这通常是很复杂的过程(参见Prentice Hall 于2000 年编写的《Thinking in C ++ (第2 版)》第10 章),因此Java 设计者认为这是很糟糕的功能,不应该纳入到Java 中。起始重载操作符并没有糟糕到只能自己去重载的地步,但具有讽刺意味的是,与C ++ 相比,在Java 中使用操作符重载要容易得多。这一点可以在Python(参见[www. Python . org](http: // www.python.org))和C#中看到,它们都有垃圾回收机制,操作符重载也简单易懂。
1516+ [^ 1 ]: C ++ 允许编程人员任意重载操作符。这通常是很复杂的过程(参见Prentice Hall 于2000 年编写的《Thinking in C ++ (第2 版)》第10 章),因此Java 设计者认为这是很糟糕的功能,不应该纳入到Java 中。起始重载操作符并没有糟糕到只能自己去重载的地步,但具有讽刺意味的是,与C ++ 相比,在Java 中使用操作符重载要容易得多。这一点可以在Python(参见[www. Python . org](http: // www.python.org))和C#中看到,它们都有垃圾回收机制,操作符重载也简单易懂。
15431517
1544- [^ 2 ]: Java 并非在一开始就支持正则表达式,因此这个令人费解的语法是硬塞进来的。
1518+ [^ 2 ]: Java 并非在一开始就支持正则表达式,因此这个令人费解的语法是硬塞进来的。
15451519
1546- [^ 3 ]: 网上还有很多实用并且成熟的正则表达式工具。
1520+ [^ 3 ]: 网上还有很多实用并且成熟的正则表达式工具。
15471521
1548- [^ 4 ]: input来自于[Galaxy Quest ](https: // en.wikipedia.org/wiki/Galaxy_Quest)中Taggart司令的一篇演讲。
1522+ [^ 4 ]: input来自于[Galaxy Quest ](https: // en.wikipedia.org/wiki/Galaxy_Quest)中Taggart司令的一篇演讲。
15491523
1550- [^ 5 ]: 我不知道他们是如何想出这个方法名的,或者它到底指的什么。这只是代码审查很重要的原因之一。
1524+ [^ 5 ]: 我不知道他们是如何想出这个方法名的,或者它到底指的什么。这只是代码审查很重要的原因之一。
15511525
15521526< ! -- 分页 -- >
15531527
0 commit comments