字符串操作是计算机程序设计中最常见的行为。
不可变 String
String
对象是不可变的,String
类中每一个看起来会修改 String
值的方法,实际上都是创建了一个全新的 String
对象,以包含修改后的字符串内容,而最初的 String
对象则丝毫未动。
重载“+” 与 StringBuilder
虽然 Java
并不允许程序员重载任何操作符,但是为 String
对象重载了 +
与 +=
。
使用 +
可以很方便的连接字符串,但是也会产生一大堆需要垃圾回收的中间对象。虽然,对于 +
,编译器进行了一定的优化,会自动产生 StringBuilder
用于连接。但是遇到循环时,就可能会创建过多的 StringBuilder
。
因此,如果字符串操作比较简单,可以使用 +
,信赖编译器,它会合理地构造最终的字符串。但是,如果操作比较复杂,或者里面存在循环,那么最好自己创建 StringBuilder
对象来进行操作。
StringBuilder
是非线程安全,StringBuffer
是线程安全的,但是也意味着开销会大些。
无意识的递归
当想要打印对象的内存地址时:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20class A {
// 如果使用 return "A: " + this; 将会得到异常
// 因为这里 String 对象紧跟着 + ,this 也会被编译器当作 String 类型
// 即 this.toString() ,这便造成了递归调用
// 所以应该使用 Object 对象的 toString() 方法
// 即 super.toString()
public String toString() {
return "A: " + super.toString();
}
}
List<A> list = new ArrayList<A>();
for (int i = 0; i < 3; i++) {
list.add(new A());
}
System.out.println(list);
// [A: A@1b6d3586, A: A@4554617c, A: A@74a14482]
格式化输出
1 | System.out.printf("%d %f\n", 1, 1.0); // 1 1.000000 |
格式化常见的抽象语法为:%[argument_index$][flags][width][.precision]conversion
。
更加详细的说明见 java.util.Formatter
- - - Java API
1 | // conversion 表示数据类型,d 代表十进制整数 |
正则表达式
在 Java
中,\\
代表正则表达式的 \
,即 \\d
代表正则表达式的 \d
。另外 \\\\
代表普通的 \
。
更加详细的说明见 java.util.regex.Pattern
- - - Java API
1 | // String 对象的 matches() 方法 |
比起功能有限的 String
类,Pattern
对象的 matcher()
方法会生成一个 Matcher
对象,有更多功能可以使用。
1 | class A { |
Pattern
类的 compile()
方法还可以接受标记参数,以调整匹配行为。
1 |
|
组是用括号划分的正则表达式,可以根据组的编号来引用某个组。例如:A(B(C))D(E)
group(0) = ABCDE
group(1) = BC
group(2) = C
group(3) = E
1 | class A { |
扫描输入
Scanner
的构造器可以接受任何类型的输入对象,包括 File
对象,String
对象等。
1 | class A { |