文章目录
String、StringBuilder、StringBuffer的区别?
String、StringBuilder、StringBuffer是java中主要操作字符串的类。三者之间的接口继承方式如下图:
1、String类和StringBuilder的区别?
(1)String为不可变字符序列,StringBuilder为可变字符序列。
String是不可变字符序列,StringBuilder是可变字符序列。也就是说,String对象一旦被创建,值不可以被改变,而StringBuilder对象被创建之后仍然可以对其值进行修改。
从内存方面讲,例如字符串的加法操作。StringBuilder是调用自身的append()方法,最后调用toString()方法将结果返回。而String再进行加法操作时则是先创建一个StringBuilder对象,其次调用StringBuilder的append()方法,最后调用toString()方法将结果返回。可见String对象的加法操作多了一些附加的操作,会产生许多无用对象,等待垃圾回收器来回收,所以会降低程序的性能。
因此,String适合在需要被共享的场合中使用,StringBuilder适合在一个字符串需要经常被修改的场景使用。
从底层实现来讲,两者都是通过字符数组实现的,StringBuilder初始容量为16个字符,在加法操作时是通过数组扩容来实现的。
(2)初始化方式有所不同。
实例化String时,可以利用构造函数String str=new String(“hello”)来初始化。也可以使用赋值String str=“hello”来初始化。
StringBuilder只可以通过构造函数的方式初始化。StringBuilder stb=new StringBuilder(“hello”)。
2、StringBuffer和StringBuilder的区别?
两者都是继承的相同接口,方法和功能几乎完全等价。
但是StringBuilder是线程不安全的。StringBuffer是线程安全的,方法大多被synchronized 关键字修饰,在多个线程访问时可以使用StringBuffer。
执行效率:StringBuilder>StringBuffer>String
使用建议:
(1)String:操作数据量比较小。
(2)StringBuilder:操作大量数据,单线程。
(3)StringBuffer:操作大量数据,多线程。
3、面试中的问题,回答了String+发生什么操作的分析,面试官接着问:那你说的StringBuilder在append()的时候发生了什么?比如原来分配的内存是10kb,后来又加了很长的字符串,中间内存是怎么分的?
当时很懵逼没有反应过来,以为是很高深的问题。面试结束后一想,其实问的是StringBuilder的底层数组扩容。
回答:
StringBuilder底层是通过可变字符数组实现的,它在append的时候,会判断然后进行一个数组扩容的过程。
如果说原字符长度加上append的字符的长度大于字符数组的长度,就会进行一个数组的扩容。
一般扩容为(原长度+1)*2,如果新的字符长度比扩容后的还大,就直接扩容为新的字符长度。
StringBuilder就是这样通过数组扩容的机制进行内存的分配的。
private StringBuilder append(StringBuilder sb) {
if (sb == null)
return append("null");
int len = sb.length();
int newcount = count + len;//新的数组长度
if (newcount > value.length)
expandCapacity(newcount);
sb.getChars(0, len, value, count);
count = newcount;
return this;
}
void expandCapacity(int minimumCapacity) {
int newCapacity = (value.length + 1) * 2;
if (newCapacity < 0) {
newCapacity = Integer.MAX_VALUE;
} else if (minimumCapacity > newCapacity) {
newCapacity = minimumCapacity;
}
value = Arrays.copyOf(value, newCapacity);
}