String是Object类的子类。
StringBuilder和StringBuffer同为AbstractStringBuilder的子类,而
AbstractStringBuilder这个抽象类中定义了该参数
char[] value;
回忆一下在String类的源码中是这样定义的;
private final char value[];
两者的区别就在于String中的value[]虽然是final但是该引用指向的内容是可变的,不过String中没有提供更改的接口,所以内容也是不可变的。反观AbstractStringBuilder中的value[]则可以供他人更改。
*StringBuilder(可变字符序列),String(不可变字符序列)
1.内存分析:
举个例子:我们要把1到100的所有数字拼起来,组成一个字符串
StringBuffer sbf = new StringBuffer();
for(int i = 0;i<100;i++)
{
sbf.append(i);
}
上面使用StringBuffer和append()方法拼接字符串的方法要比下面使用String的方法高效很多。原因就在于,String在jvm中是不可变的下面看起来str改变了是因为创建了多个字符串,且让str指向改变。
这样一来,用String来实现的方法会创建101个对象。远多于StringBuffer。
String str= new String();
for(int i = 0;i<100;i++)
{
str = str+i;
}
2.动态数组扩容:数组一旦创建它的大小就不可变了。(注:在数组中length是属性,而在String中length()是方法,而在StringBuffer的父类AbstractStringBuilder中也有length方法)那么StringBuffer是如何实现数组扩容的呢?
StringBuffer在扩容时会用super()调用父类的重载构造方法。
public StringBuilder(String str) {
super(str.length() + 16);
append(str);
}
父类AbstractStringBuilder中:
void expandCapacity(int minimumCapacity) {
int newCapacity = value.length * 2 + 2;
if (newCapacity - minimumCapacity < 0)
newCapacity = minimumCapacity;
if (newCapacity < 0) {
if (minimumCapacity < 0) // overflow
throw new OutOfMemoryError();
newCapacity = Integer.MAX_VALUE;
}
value = Arrays.copyOf(value, newCapacity);
}
先判断是否需要扩容再讲述组扩容成原来的2倍加2。并把原来的数组复制到新数组中去。
3.equals方法的实现重写:
String中重写了equals()方法和hashCode()方法,而StringBuffer并没有重写,所以将StringBuffer类储存进集合类中时会出现问题。
网友评论