String对象是不可变的,String类中每一个看起来会修改String值的方法,实际上都是创建了一个全新的String对象,以包含修改后的字符串内容。而最初的String对象则丝毫未动。
不可变性会带来一定的效率问题。为String对象重载的“+”操作符就是一个例子(用于String的“+”与“+=”是Java中仅有的两个重载过的操作符,而Java并不允许程序员重载任何操作符)。操作符“+”可以用来连接String:
public class Concatenation{
public static void main(String[] args){
String mango = "mango" ;
String s = "abc"+ mango + "def" +47 ;
System.out.println(s) ;
}
}
在这个例子中,编译器自动引入了java.lang.StringBuilder类,因为它更高效。编译器创建了一个StringBuilder对象,用以构造最终的String,并未每个字符串调用一次StringBuilder的append()方法,总计四次。最后调用toString()生成结果。
public class WhitherStringBuilder {
public String implicit(String[] fields){
String result = "";
for(int i = 0; i < fields.length; i++)
result += fields[i];//每进行一次“+”操作符运算,就会生成一个StringBuffer对象
return result;
}
public String explicit(String[] fields){
StringBuffer result = new StringBuffer();
for(int i = 0; i < fields.length; i++)
result.append(fields[i]);//这样只会有一个StringBuffer对象
return result.toString();
}
}
显式地创建StringBuilder还允许你预先为其指定大小,可以避免多次重新分配缓冲。
在为一个类编写toString()方法时,如果字符串操作比较简单,那就可以信赖编译器,它会为你合理地构造最终的字符串结果。但是,如果你要在toString()方法中使用循环,那么最好自己创建一个StringBuilder对象,用它来构造最终的结果。
如果想走捷径,例如append(a+ ":" +c),那编译器就会掉入陷阱,从而为你另外创建一个StringBuilder对象处理括号内的字符串操作。