String、StringBuffer、StringBuilder 忘是亡心i 2022-02-13 08:19 224阅读 0赞 字符串在开发中经常使用到,但是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<String>, 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基本相同。
还没有评论,来说两句吧...