String:
String最常用的字符串,在java中String属于对象,同时由于String类是final修饰的,所以String的值是无法改变的。看到这里肯定有疑问 比如以下代码:
String a = "abd";
System.out.println(a);//abd
a="c12";
System.out.println(a);//c12
运行结果后,发现控制台a的值的确改变了
那么String的值无法改变,这又是怎么回事呢?
要理解这个,首先就得明白String是引用类型。第一句 String a = “abd”,此时在堆内存中已经创造了“abd”这个对象,下一句a=“c12”,其实是在堆内存中继续创造了“c12”这个对象,a的值之所以会发生改变,是因为a的指向从 “abd”变成了“c12”。因此值看起来是改变了,其实是没有改变的,如下图:
“c12”。因此值看起来是改变了,其实是没有改变的,如下图:
字符串频繁的指向“断开-重写连接”会大大降低性能,同时因为开拓了更多的空间,也会对内存造成威胁,因此对于要经常修改内容的情况,建议使用**:StringBuilder、StringBuffer**.
StringBuffer字符串变量(线程安全)
StringBuilder 字符串变量(非线程安全)
效率:StringBuilder>StringBuffer>String ;
原因:StringBuffer与StringBuilder都是继承自同一个抽象类,基本上方法都一样,实现也几乎都是一样的,而导致StringBuffer效率低一的原因就是StringBuffer的几乎所有方法都加synchronized(同步锁)。
不论怎样,方法只要加了synchronized同步,效率就是比不加synchronized的低。为了确保多线程下的安全,牺牲点效率也还行。
StringBuffer
在实际开发当中,我们经常会使用到字符串连接的操作,如果用String来操作,则使用“+”号完成字符串的连接操作;
这种连接字符串,代码性能非常低,解决这个问题的方法是使用StringBuffer类的方法.
StringBuffer的内部实现采用字符数组,默认数组的长度为16,超过数组大小时,动态扩充的算法是原来的长度*2+2
所以当我们预知要添加的数据长度时,建议使用带初始化容量的构造方法,来避免动态扩充的次数,从而提高效率。
StringBuffer常用方法:
append(String str) :将指定的字符串追加到此字符序列;
charAt(int index) : 返回此序列中指定索引处的 char 值;
deleteCharAt(int index) : 移除此序列指定位置的 char。
substring(int start) : 返回一个新的 String,它包含此字符序列当前所包含的字符子序列
StringBuilder 常用方法和StringBuffer一样
三者共同之处:都是final类,不允许被继承