String, StringBuffer, StringBuilder比较

String 类

String 类表示一个字符串。 在设计上, 字符串类存储的字符串是不可变的(immutable)。想要修改一个字符串的内容只能通过新建一个新的字符串实例来实现。 且对于两个相同的字符串字面量而言, 他们指向的是同一个字符串对象。

并且String类相对于其他类, 具有以下特殊性:

  • String类是Java中唯一的具有重载运算符的类。 String重载了+运算符, 使得对于一个加号左右两边的String能够被连接起来。

成员变量

String类具有以下的关键成员变量:

final char[] value

存储组成这个字符串的字符数组。 因为是final声明, 所以在类被创建之后是不可修改的。

final int count

存储在value[]数组中的字符个数, 在大多数情况下与value.length中的值相同。

final int offset

存储在value[]数组中字符的起始位置。 此变量的创建目的是为了substring()方法提供便利

私有类

private static final class CaseInsensitiveComparator

String类私有类, 其具有compare()方法, 用于提供对于字符串之间的大小写不敏感的比较。

构造器

public String ()

默认构造器, 创建一个空的字符串, 设置value为"",offset为0,count为0。

public String (String str)

拷贝构造器, 根据传入的参数str,新建一个新的字符串实例。但由于字符串是不可变的, 所以拷贝是以浅拷贝的方式执行的。

public String (char[] data)

根据传入的data字符数组, 初始化一个新的字符串实例。

public String (char[] data, int offset, int count)

根据传入的data字符数组, offset偏移量和count数据, 来初始化一个新的字符串实例。

public String (byte[] ascii, int hibyte, int offset, int count)

使用二进制的方式初始化一个字符串, 其中ascii数组中存放每一个字符的ascii码。 并且最终每一位的值c = (char)(((hibyte & 0xff) << 8) | (b & 0xff))

即用hibyte填充最终字符的最高八位,以及用ascii数组的值填充低八位。

public String (byte[] ascii, int hibyte)

使用String (byte[] ascii, int hibyte, int offset, int count) 作为 Delegate Constructor, 默认offset为0, count为ascii.length

public String (byte[] data, int offset, String encoding)

使用encoding参数所规定的方式来解码由data数组传入的字符, 并依此新建一个字符串。

public String (StringBuffer buffer)

使用StringBuffer中存储的字符序列构造一个新的字符串。StringBuffer中字符的改动并不会影响通过此构造器构建的字符串。

public String (StringBuilder buffer)

使用StringBuilder中的字符序列构造一个新的字符串, StringBuilder中字符的改动并不会影响通过此构造器构建的字符串。

StringBuffer 类

StringBuffer类表示一个 可变的(changeable) 字符串, 它提供了一系列成员方法来对StringBuffer实例进行修改, 包括insert, replace, delete, appendreverse等。

StringBuffer实例是变长的, 所以尽管在定义时, 可能是以固定长度定义的, 但它的长度都可以进行不断正常。

出于某种特定的原因, 编译器一般使用StringBuffer来重载+运算符对于String类型的运算。 即表达式str_a+str_b, 等价于
new StringBuffer().append(str_a).append(str_b).toString()

成员变量

StringBuffer类拥有以下的关键成员变量:

int count

下一个可用buffer位置的索引, 同时也是当前字符串内容的大小。 注意此处count是public权限, 即程序可以从外部访问该变量。

char[] value

存储StringBuffer中的字符串Buffer本身。

boolean shared

标记Buffer是否与其他对象共享, 如果为真, 则在对字符串进行写操作时, 需要先将其复制一份。

构造器

public StringBuffer()

默认构造器, 在默认情况下, 会构建一个以DEFAULT_CAPACITY为大小的StringBuffer,在JDK1.2中, 这个值为16.

public StringBuffer(int capacity)

这个构造器会新建一个大小为capacitychar数组, 并且将其作为成员变量value的当前值。

public StringBuffer(String str)

这个构造器接受一个String参数,并将其值赋予countvalue,需要注意的是,通过此构造器得到的字符串Buffer的大小是原字符串的大小加上DEFAULT_CAPACITY。但是字符串的大小(length)依然是原字符串

StringBuilder类

StringBuilder类表示一个 可变的(changeable) 字符串, 与StringBuffer类似, 它也提供了诸如insert,replace,delete, append, reverse之类的方法。 但是与StringBuilder不同的是,StringBuilder是不同步的, 只能在一个线程的情况下使用。

关键成员函数

int count

下一个可用buffer位置的索引, 同时也是当前字符串内容的大小。

char[] value

存储StringBuilder中的字符串Buffer本身。

构造器

public StringBuilder()

默认构造器, 创建构建一个以DEFAULT_CAPACITY为大小的StringBuilder

public StringBuilder(int capacity)

这个构造器会新建一个大小为capacity的char数组, 并且将其作为变量value的当前值。

public StringBuilder(String str)

这个构造器会根据传入的String参数,并将其值赋予countvalue。 StringBuilder通过此构造器得到的实例对象与StringBuffer一样, value数组的大小会空余一个DEFAULT_CAPACITY

public StringBuilder(CharSequence seq)

根据传入的CharSequence参数, 新建一个StringBuilder实例。 大小同样是有一个DEFAULT_CAPACITY的空余。

比较异同

String与(StringBuffer及StringBuilder)进行比较

相同点:

  1. 都表示了一个字符串序列
  2. 都是final类, 都不允许被继承
  3. 这个字符串序列都是支持Unicode的
  4. 都支持对于字符串序列内容的部分读取
  5. 都重载了加号运算符, 能够直接使用”+”来连接两个字符串

不同点:

  1. String类型的字符串是 不可变(immutable) 的, 即一个String实例在被创建之后, 其字符串的大小, 内容不能再被改变。 如果需要进行改变的话, 实际上是新建了一个String实例。
  2. 而对于StringBuffer和StringBuilder而言, 其本质上实现了一个变长数组(VLA),所以其字符串大小,内容都是可以进行变化的。在进行修改的时候, StringBuffer和StringBuilder各自实现了一个public void ensureCapacity(int minimumCapacity)的方法, 以确保时刻Buffer数组的大小要大于minimumCapacity, 否则就将数组扩充成其原来size的两倍再加二。
  3. String类型对于字符串本身的操作更多,诸如toLowerCase, toUpperCase这类大小写转换的方法, 以及matches, split,replace这类正则表达式方法, 以及trimconcat这类操作字符串的方法,都仅在String类中实现,而在StringBuffer与StringBuilder类中并没有提供以上接口。

StringBuffer 与 StringBuilder进行比较

相同点:

  1. 前面与String类型共有的相同点不赘述
  2. StringBuffer类与StringBuilder类都实现了一个 可变的(changeable) 字符串对象, 可以通过一系列方法对字符串内容进行诸如增加,删减,插入,替换,翻转等操作。
  3. 实现的字符串buffer的本质都是一个变长数组(VLA), 在任何时刻都尽量保证数组不越界, 如果接近了其边界, 就将数组的大小扩充成原来大小的两倍加二。
  4. 默认的buffer大小DEFAULT_CAPACITY都为16

不同点:

  1. StringBuilder类相较StringBuffer, 多了一个基于CharSequence建立的构造器。
  2. StringBuffer比StringBuilder类多了一个shared指示,以标记buffer内容是否被多个对象所引用。如果被多个引用的话,在进行操作的时候就要将这个buffer再复制一份, 以保证其单引用的性质。 这一点其实是为了保证操作内容的同步化进行的。
  3. 正如之前所说, StringBuffer和StringBuilder的最大不同点在于其操作的同步性。 StringBuffer在其大多数成员方法前都加上了synchronized关键字, 以保证其线程安全。 也就是说, 在同一时间, 只有一个线程能够对同一个StringBuffer对象进行操作,这种限制避免了线程之间读写的冲突。 而对于StringBuilder来说, 就没有这一层限制。故其有可能会引起线程之间的冲突, 但从另一个角度而言, 也减少了诸如线程锁之类的可能的系统开销。 故相比StringBuffer而言, StringBuilder的速度可能会更快一些。 故两者需要权衡使用。