刚开始学习时,书籍、老师、教程都只介绍到 String 不可变,StringBuffer 线程安全,StringBuilder 线程不安全,一直都是死记硬背,还总是弄糊涂,现知其然知其所以然。
String
String 类对象代表不可变的Unicode字符序列,所以称为不可变对象。
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0
/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -6849794470754667710L;
}
private final char value[];
String字符串值是存储在 char 类型的 value[] 数组中,而数组定义是为 final
的,所以 String 类型赋值后不可变。
而我们对 String 对象的改变,实际是生成新的对象,改变指针指向。
若常改变字符串内容使用 String,将会产生许多对象,对系统性能产生影响,所以最好不使用 String。
StringBuffer
StringBuffer继承AbstractStringBuilder
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
{}
而 AbstractStringBuilder 中字符串也是存储在 char value[]
,但是并没有 final
修饰,所以 StringBuffer 是可变的,修改值 hashCode 地址没变。
abstract class AbstractStringBuilder implements Appendable, CharSequence {
/**
* The value is used for character storage.
*/
char[] value;
/**
* The count is the number of characters used.
*/
int count;
}
StringBuffer是线程安全的,因为其方法都添加了同步锁 synchronized
,所以一般使用在全局变量
上
@Override
public synchronized int length() {
return count;
}
@Override
public synchronized int capacity() {
return value.length;
}
@Override
public synchronized void ensureCapacity(int minimumCapacity) {
super.ensureCapacity(minimumCapacity);
}
/**
* @since 1.5
*/
@Override
public synchronized void trimToSize() {
super.trimToSize();
}
/**
* @throws IndexOutOfBoundsException {@inheritDoc}
* @see #length()
*/
@Override
public synchronized void setLength(int newLength) {
toStringCache = null;
super.setLength(newLength);
}
/**
* @throws IndexOutOfBoundsException {@inheritDoc}
* @see #length()
*/
@Override
public synchronized char charAt(int index) {
if ((index < 0) || (index >= count))
throw new StringIndexOutOfBoundsException(index);
return value[index];
}
StringBuilder
StringBuilder继承AbstractStringBuilder,同样可变,修改值 hashCode 地址没变。
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
{}
StringBuffer是非线程安全的,因为其方法是直接继承 AbstractStringBuilder 的,未添加同步锁。所以一般使用在局部变量
,用完后丢弃
/**
* Returns the length (character count).
*
* @return the length of the sequence of characters currently
* represented by this object
*/
@Override
public int length() {
return count;
}
/**
* Returns the current capacity. The capacity is the amount of storage
* available for newly inserted characters, beyond which an allocation
* will occur.
*
* @return the current capacity
*/
public int capacity() {
return value.length;
}
/**
* Ensures that the capacity is at least equal to the specified minimum.
* If the current capacity is less than the argument, then a new internal
* array is allocated with greater capacity. The new capacity is the
* larger of:
* <ul>
* <li>The {@code minimumCapacity} argument.
* <li>Twice the old capacity, plus {@code 2}.
* </ul>
* If the {@code minimumCapacity} argument is nonpositive, this
* method takes no action and simply returns.
* Note that subsequent operations on this object can reduce the
* actual capacity below that requested here.
*
* @param minimumCapacity the minimum desired capacity.
*/
public void ensureCapacity(int minimumCapacity) {
if (minimumCapacity > 0)
ensureCapacityInternal(minimumCapacity);
}
/**
* For positive values of {@code minimumCapacity}, this method
* behaves like {@code ensureCapacity}, however it is never
* synchronized.
* If {@code minimumCapacity} is non positive due to numeric
* overflow, this method throws {@code OutOfMemoryError}.
*/
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (minimumCapacity - value.length > 0) {
value = Arrays.copyOf(value,
newCapacity(minimumCapacity));
}
}
*
String:String中对象是不可变的,可理解为常量,即线程安全的。
StringBuffer:对象可变,线程安全,效率比 String 高。
StringBuilder:对象可变,线程不安全,效率比 StringBuffer 高(常用,官方推荐优先使用,因为速度快)。
说明:
StringBuffer 在 JDK1.0 引入,StringBuilder 在 JDK1.5引入,都是直接继承 Object 类,没有继承 AbstractStringBuilder 抽象类,----------咦,有问题,研究研究,是API文档中不显示 Abstract 类?都显示直接继承 Object,我使用的是1.8,这里又是继承的 AbstractStringBuilder 类?2018/9/27 2:12
为啥速度快?
String消耗创建对象时间,所以慢,StringBuilder比StringBuffer快,是因为StringBuffer的方法添加的同步锁,会影响性能,所以StringBuffer慢点