字符串操作是计算机程序设计中最常见的行为。
不可变 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) = ABCDEgroup(1) = BCgroup(2) = Cgroup(3) = E
1 | class A { |
扫描输入
Scanner 的构造器可以接受任何类型的输入对象,包括 File 对象,String 对象等。
1 | class A { |