String
java.lang.String 类表示字符串。
- java.lang.String 是 final 修饰的,所以不能够被继承;
- private final char value[] 变量用户存储字符串数组的,所以String对象是不可变的;
- 因为String不可变性,所以是线程安全的。
注意:在 Java 9 之后,java.lang.String 类的实现改用 byte 数组存储字符串的:private final byte[] value;
StringBuilder
java.lang.StringBuilder 类继承自 java.lang.AbstractStringBuilder 类,AbstractStringBuilder 类中也是使用字符数组保存字符串 char[] value,但是没有使用 final 关键字修饰,所以StringBuild对象是可变的。
StringBuilder 的构造函数是调用父类AbstractStringBuilder的构造函数实现的。
StringBuilder 类的父类 AbstractStringBuilder 中实现了 expandCapacity、append、insert、indexOf 等公共方法,StringBuilder 没有实现线程的同步,当多线程操作同一个 StringBuilder 对象时可能会产生线程安全问题。
StringBuffer
StringBuffer 和 StringBuilder 类似,但是 StringBuffer 是线程安全的,StringBuffer 在方法上使用 synchronized 关键字来实现线程安全。所以效率相对于 StringBuilder 会稍微低一些,10% 左右,但是在多线程情况下 StringBuffer 可以保证线程安全。
线程安全
String 对象是不可变的,也就可以理解为常量,线程安全;
StringBuilder 为对线程进行同步,线程不安全;
StringBuffer 使用 synchronized 关键字修饰了方法,可以认为是线程安全的。
性能对比
String 对象进行更新时,是创建新的String对象,然后将指针指向新String对象,速度较慢;
StringBuffer 更新时是针对自身进行修改,但方法使用synchronized进行加锁,速度较快;
StringBuilder 更新时是针对自身进行修改,且方法没有加速,速度最快;
相同情况下 StringBuilder 相比于 StringBuffer 大概有 10%~15% 左右的性能提升,但却存在线程不安全的风险。
小结
- 操作少量数据:适用 String;
- 单线程操作字符串缓冲区下操作大量数据:适用 StringBuilder;
- 多线程操作字符串缓冲区下操作大量数据:适用 StringBuffer