String,Stringbuffer,StringBuilder
String类
java中String是一个特殊的包装类数据。
String不属于8种基本数据类型,String是一个对象。 因为对象的默认值是null,所以String的默认值也是null;但它又是一种特殊的对象,有其它对象没有的一些特性。
String str=”kvill”;
String str=new String (“kvill”);的区别:
在这里,我们不谈堆,也不谈栈,只先简单引入常量池这个简单的概念。 常量池(constant pool)指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口等中的常量,也包括字符串常量。这也说明String不可变的。
关于String的不可变设计:
String是不可改变类(记:基本类型的包装类都是不可改变的)的典型代表,也是Immutable设计模式的典型应用,String变量一旦初始化后就不能更改,禁止改变对象的状态,从而增加共享对象的坚固性、减少对象访问的错误,同时还避免了在多线程共享时进行同步的需要。
至于什么是Immutable设计模式,请自行百度。
String的不可变性导致字符串变量使用+号的代价:
通过一个String例子引出Stringbuffer,StringBuilder
Sting s="a"
String s1="b"
String s2="c"
String s3=s+s1+s2;
分析:变量s的创建等价于 String s 3= “abc”; 由上面例子可知编译器进行了优化,这里只创建了一个对象。由上面的例子也可以知道s3不能在编译期进行优化,其对象创建相当于:
StringBuffer temp = new StringBuffer();
temp.append(s).append(s2).append(s3);
String s = temp.toString();
由上面的分析结果,可就不难推断出String 采用连接运算符(+)效率低下原因分析:
每做一次 + 就产生个StringBuffer对象,然后append后就扔掉。下次循环再到达时重新产生个StringBuffer对象,然后append 字符串,如此循环直至结束。如果我们直接采用StringBuffer对象进行append的话,我们可以节省N - 1次创建和销毁对象的时间。所以对于在循环中要进行字符串连接的应用,一般都是用StringBuffer或StringBulider对象来进行append操作。
故Stringbuffer,StringBulider在进行字符串处理时,不生成新的对象,在内存使用上要优于String类。所以在实际使用时,如果经常需要对一个字符串进行修改,例如插入、删除等操作,使用StringBuffer要更加适合一些。
Stringbuffer 线程安全
StringBulider 非线程安全
总结建议:
(1)基本原则:如果要操作少量的数据,用String ;单线程操作大量数据,用StringBuilder ;多线程操作大量数据,用StringBuffer。
(2)不要使用String类的”+”来进行频繁的拼接,因为那样的性能极差的,应该使用StringBuffer或StringBuilder类,这在Java的优化上是一条比较重要的原则
(3)相同情况下使用 StirngBuilder 相比使用 StringBuffer 仅能获得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险。而在现实的模块化编程中,负责某一模块的程序员不一定能清晰地判断该模块是否会放入多线程的环境中运行,因此:除非确定系统的瓶颈是在 StringBuffer 上,并且确定你的模块不会运行在多线程模式下,才可以采用StringBuilder;否则还是用StringBuffer