String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且大量浪费有限的内存空间,StringBuffer是可变类,和线程安全的字符串操作类,任何对它指向的字符串的操作都不会产生新的对象,StringBuffer和StringBuilder类功能基本相似
1. String 类
String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且大量浪费有限的内存空间。
String a = "a"; //假设a指向地址0x0001
a = "b";//重新赋值后a指向地址0x0002,但0x0001地址中保存的"a"依旧存在,但已经不再是a所指向的,a 已经指向了其它地址。
因此String的操作都是改变赋值地址而不是改变值操作。
2. StringBuffer是可变类且线程安全的字符串操作类,任何对它指向的字符串的操作都不会产生新的对象。 每个StringBuffer对象都有一定的缓冲区容量,当字符串大小没有超过容量时,不会分配新的容量,当字符串大小超过容量时,会自动增加容量。
StringBuffer buf=new StringBuffer(); //分配长16字节的字符缓冲区
StringBuffer buf=new StringBuffer(512); //分配长512字节的字符缓冲区
StringBuffer buf=new StringBuffer("this is a test")//在缓冲区中存放了字符串, 并在后面预留了16字节的空缓冲区。
3.StringBuilder
StringBuffer和StringBuilder类功能基本相似,主要区别在于StringBuffer类的方法是多线程、安全的,而 StringBuilder不是线程安全的,相比而言,StringBuilder类会略微快一点。对于经常要改变值的字符串应该使用StringBuffer和StringBuilder类。
4.线程安全
StringBuffer 线程安全
StringBuilder 线程不安全
5.速度
一般情况下,速度从快到慢:StringBuilder>StringBuffer>String,这种 比较是相对的,不是绝对的。
6.总结
(1).如果要 操作少量的数据用 = String
(2). 单线程操作字符串缓冲区 下操作 大量数据 = StringBuilder
(3). 多线程操作字符串缓冲区 下操作 大量数据 = StringBuffer
String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且大量浪费有限的内存空间。
String a = "a"; //假设a指向地址0x0001
a = "b";//重新赋值后a指向地址0x0002,但0x0001地址中保存的"a"依旧存在,但已经不再是a所指向的,a 已经指向了其它地址。
因此String的操作都是改变赋值地址而不是改变值操作。
2. StringBuffer是可变类且线程安全的字符串操作类,任何对它指向的字符串的操作都不会产生新的对象。 每个StringBuffer对象都有一定的缓冲区容量,当字符串大小没有超过容量时,不会分配新的容量,当字符串大小超过容量时,会自动增加容量。
StringBuffer buf=new StringBuffer(); //分配长16字节的字符缓冲区
StringBuffer buf=new StringBuffer(512); //分配长512字节的字符缓冲区
StringBuffer buf=new StringBuffer("this is a test")//在缓冲区中存放了字符串, 并在后面预留了16字节的空缓冲区。
3.StringBuilder
StringBuffer和StringBuilder类功能基本相似,主要区别在于StringBuffer类的方法是多线程、安全的,而 StringBuilder不是线程安全的,相比而言,StringBuilder类会略微快一点。对于经常要改变值的字符串应该使用StringBuffer和StringBuilder类。
4.线程安全
StringBuffer 线程安全
StringBuilder 线程不安全
5.速度
一般情况下,速度从快到慢:StringBuilder>StringBuffer>String,这种 比较是相对的,不是绝对的。
6.总结
(1).如果要 操作少量的数据用 = String
(2). 单线程操作字符串缓冲区 下操作 大量数据 = StringBuilder
(3). 多线程操作字符串缓冲区 下操作 大量数据 = StringBuffer
(4)在StringBuffer与StringBuilder中都有.toString()的方法将其转换为String,这是在实际应用中经常用到的。
一个值得注意很容易忽略的问题,看下面代码:
public class Demo{
public static void main(String[] args) {
StringBuilder sb1=new StringBuilder("strBuilder");
StringBuilder sb2=new StringBuilder("strBuilder");
String s1 = new String("str");
String s2 = new String("str");
System.out.println("StringBuilder的equals结果:" + sb2.equals(sb1));
System.out.println("StringBuilder的equals结果:" + s2.equals(s1));
System.out.println("StringBuilder的toString()比较结果:"
+ sb2.toString().equals(sb1.toString()));
}
}
运行结果:
StringBuilder的equals结果:false
StringBuilder的equals结果:true
StringBuilder的toString()比较结果:true
说明:String类里重写了equals()方法,使其之比较字符串的内容,所以结果为true;但是StringBuilder类并没有重写equals()方法,所以默认比较的是存储地址,又因为sb1、sb2尽管其内容相同,但实际上是两个对象,其存储的位置可定不相同,所以结果为false。在根据上面所说的toString ()方法将StringBuilder对象转换成String对象进行比较,这时比较的是内容,所以结果为true。public class Demo{
对于StringBuffer,有一点容易被忽略,值得注意:
public static void main(String[] args) {
StringBuffer sbf = new StringBuffer("hello");
//System.out.printf(sbf); //错误!(无法通过方法调用转换将实际参数St ringBuffer转换为String)
System.out.printf(sbf.toString());
}
}
在StringBuffer里面没有方法可以直接打印StringBuffer对象的内容,一般是调用toString()方法进行转换。