Java编译器对String做了特殊处理,使得我们可以直接用+拼接字符串。
public class catchExample2 { public static void main(String[] args) { String s = ""; for (int i = 0; i < 100;i++) { s = s + "," + i; } System.out.println(s); } }
虽然可以直接拼接字符串,但是每一次循环都会创建一个新的字符串对象,
然后扔掉旧的字符串对象,这样绝大多数对象都是临时对象,这样非常浪费内存。
为了能高效拼接字符串,Java标准库提供了StringBuilder,它是一个可变对象,
可预分配缓冲区,这样,往StringBuilder中新增字符时,不会创建新的临时对象
public class catchExample2 { public static void main(String[] args) { StringBuilder s = new StringBuilder(1024); for (int i = 0; i < 100;i++) { s.append(","); s.append(i); } System.out.println(s); } }
StringBuilder还可以进行链式操作。
public class catchExample2 { public static void main(String[] args) { StringBuilder s = new StringBuilder(1024); s.append("Mr ") .append("Bob") .append("!") .insert(0,"Hello, "); System.out.println(s); } }
查看StringBuilder的源码,可以发现,进行链式操作的关键是,
定义的append()方法会返回this,这样就可以调用自身的其他方法。
public StringBuilder append(String str) { super.append(str); return this;
}
这是我觉得设计的非常巧妙地地方,我们可以类似地构建一个计数器:
package com.imooc.iexecption; class Addr { private int sum = 0; public Addr add(int n) { sum += n; return this; } public Addr inc() { sum ++; return this; } public int value() { return sum; } } public class catchExample2 { public static void main(String[] args) { Addr addr = new Addr(); addr.add(3).add(4).add(5).inc(); System.out.println(addr.value()); } }
对于普通的字符串+操作,并不需要我们将其改写为StringBuilder,
因为Java编译器在编译时就自动把多个连续的+操作编码为StringConcatFactory的操作。
在运行期,StringConcatFactory会自动把字符串连续操作优化为数组复制或者StringBuilder操作。