String、StringBuffer、StringBuilder

字符串在开发中经常使用到,但是Java中提供三种字符串操作的类,String、StringBuffer以及StringBuilder,那么它们有什么区别以及怎么使用呢?
从概念上讲,Java字符串就是Unicode字符序列,例如,串"Java\u2122"由5个Unicode字符J、a、v、a和TM 。Java没有内置的字符串类型,而是在标准Java类库中提供了一个预定义类,很自然的叫做String。每个双引号“”括起来的字符串都是String类的一个实例:

创新互联建站专注于成都网站制作、成都网站建设、网页设计、网站制作、网站开发。公司秉持“客户至上,用心服务”的宗旨,从客户的利益和观点出发,让客户在网络营销中找到自己的驻足之地。尊重和关怀每一位客户,用严谨的态度对待客户,用专业的服务创造价值,成为客户值得信赖的朋友,为客户解除后顾之忧。

String e = "";   //an empty string
String greeting = "Hello";

那么这三者的区别是什么?

1、可变性

查看源码简单来说,String类中使用final关键字修饰的字符数组保存字符串,所以String对象是不可变的:
String.java

public final class String implements java.io.Serializable, Comparable, CharSequence {
    private final char value[];
    private int hash;
    ...
}

而StringBuilder和StringBuffer都继承自AbstractStringBuilder,在AbstractStringBuilder类中也是使用字符数组来保存字符串的,但是没有用final关键字修饰:
AbstractStringBuilder.java

abstract class AbstractStringBuilder implements Appendable, CharSequence {
    char[] value;
    int count;
    AbstractStringBuilder(){
    }
    AbstractStringBuilder(int capacity){
        valeu = new char[capacity];
    }
    ...
}

StringBuilder.java

public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence{
    public StringBuilder() {
        super(16);
    }
    ...
}

StringBuffer.java

public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence{
    private transient char[] toStringCache;
    public StringBuffer() {
        super(16);
    }
    ...
}

从而也可以看出三个类也是用final修饰的,所以是不可继承的。

2、线程安全性

String中的对象是不可变的,也可以理解为常量,线程安全。AbstractStringBuilder是StringBuilder和StringBuffer的父类,定义了一些字符串的基本操作,如expandCapacity、append、insert、indexOf等公共方法。StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。而StringBuilder并没有对方法加同步锁,所以是线程不安全的。

3、性能

每次对String进行改变的时候,都会生成一个新的String对象,然后将引用指向新的String对象。StringBuffer和StringBuilder每次都是对对象本身进行操作,而不生成新的对象也不改变引用的指向。相同情况下使用StringBuilder相比使用StringBuffer仅能获得10%-15%左右的性能提升,却要冒线程不安全的风险。

4、使用建议

  1. 操作少量数据 String
  2. 单线程,字符串缓冲区下操作大量数据 StringBuilder
  3. 多线程,字符串缓冲区下操作大量数据 StringBuffer

5、常用API

  • java.lang.String
//返回给定位置的代码单元。
char charAt(int index)

//按照字典顺序,如果字符串位于other之前,返回一个负数;如果字符串在other之后,返回一个正数;如果两个字符串相等,返回0.
int compareTo(String other)

//用数组中offset开始的count个码点构成一个字符串
new String(int[] codePoints, int offset, int count) 

//如果字符串与other相等,返回true,反之返回false
boolean equals(Object other)

//如果字符串与other相等(忽略大小写),返回true,反之返回false
boolean equalsIgnoreCase(String other) 

//如果字符串以prefix开头,返回true
boolean startsWith(String prefix) 

//如果字符串以suffix结尾,返回true
boolean endsWith(String suffix)

//返回字符串str或代码点cp匹配的第一个子串开始的位置。这个位置从索引0或者fromIndex开始计算。
//如果在原始串中不存在str,返回-1
int indexOf(String str)
int indexOf(String str, int fromIndex) 
int indexOf(int cp) 
int indexOf(int cp, int fromIndex) 

//返回字符串str或代码点cp匹配的最后一个子串开始的位置。这个位置从原始串结尾端或fromIndex开始计算
int lastIndexOf(String str)
int lastIndexOf(String str, int fromIndex) 
int lastIndexOf(int cp) 
int lastIndexOf(int cp, int fromIndex) 

//返回字符串的长度
int length() 

//返回一个新字符串。这个字符串用newString代替原始字符串中所有oldString。
//可以用String或StringBuffer或StringBuilder对象作为CharSequence参数。
String replace(CharSequence oldString, CharSequence newString) 

//返回一个新字符串。这个字符串包含原始字符串中从beginIndex到串尾的所有代码单元
String substring(int beginIndex)

//返回一个新字符串。这个字符串包含原始字符串中从beginIndex到endindex-1的所有代码单元
String substring(int beginIndex, int endIndex)

//返回一个新字符串。这个字符串将原始字符串中的大写改为小写
String toLowerCase()

//返回一个新字符串。这个字符串将原始字符串中的小写改为大写
String toUpperCase()

//返回一个新字符串。这个字符串将删除原始字符串头部和尾部的空格
String trim()

//返回一个新字符串。用给定的定界符连接所有元素
String join(CharSequence delimiter, CharSequence... elements)
  • java.lang.StringBulider
//构造一个空字符串构建器
StringBuilder()

//返回构建器或缓冲器中的代码单元数量
int length()

//追加一个字符串并返回this
StringBuilder append(char c)

//将第i个代码单元设置为c
void setCharAt(int i, chanr c)

//在offset位置插入一个字符串并返回this
StringBuilder insert(int offset, String str)

//删除偏移量从startIndex到endIndex-1的代码单元并返回this
StringBuilder delete(int startIdnex, int endIndex)

//返回一个与构建器或缓冲器内容相同的字符串
String toString()
  • java.lang.StringBuffer
    与StringBuilder基本相同

本文名称:String、StringBuffer、StringBuilder
本文网址:http://scyanting.com/article/gppdjj.html