要弄清楚Java之中的Buffer的作用,首先需要明白java之中Wrapper类型都是不可变的。什么是不可变类型呢?顾名思义,就是这种类型的对象一旦创建好之后,无论调用何种方法都无法改变该对象的任何的属性。你看看String类的源代码就会发现,它的所有的属性都是private final的,因此只有在构造String对象的时候,这些属性才是可以修改的。 String类的方法中需要返回一个String的,如substring,concat等,都会先构造一个新的String对象,然后返回,而原来的String对象是不会发生变化的。
这样,如果需要用大量的小字符串拼接成一个长的字符串的时候,就会构造大量的中间的字符串。如下面的例子:
最后一个循环执行的时候,就会生成大量的字符串临时对象:
这10个String对象之中,我们需要的只是最后的一个,前面的9个都会浪费内存。如果情况更糟的话,有几百个上千个,或者中间的字符串更长,浪费将会更加的严重。 StringBuffer就是为了解决这个问题。它是可变的,当修改或者追加字符串到原来的对象上是,不会新生成一个字符串,而是在原来的对象上进行修改。这样,就不用分配大量的空间给中间的临时对象了。 其他的Buffer也是类似的原理。
另外, StringBuffer类是线程安全的 ,在实现的时候会有大量的代码来处理同步,如果程序只是单线程的,这样会大大的降低执行的效率。这种情况下面应该考虑使用 StringBuilder ,它和StringBufer的方法完全一样,但不是线程安全的, 执行速度也更快。
这样,如果需要用大量的小字符串拼接成一个长的字符串的时候,就会构造大量的中间的字符串。如下面的例子:
- String [] arr1 = new String[10];
- for (int i=0; i<arr1.length; i++)
- arr1[i] = "Value" + i;
- String result = "";
- for(String s : arr1) {
- result = result + s;
- }
- Value0
- Value0Value1
- Value0Value1Value2
- Value0Value1Value2Value3
- ....
- Value0Value1Value2Value3Value4Value5Value6Value7Value8Value9
另外, StringBuffer类是线程安全的 ,在实现的时候会有大量的代码来处理同步,如果程序只是单线程的,这样会大大的降低执行的效率。这种情况下面应该考虑使用 StringBuilder ,它和StringBufer的方法完全一样,但不是线程安全的, 执行速度也更快。