JDK提供了String、StringBuilder和StringBuffer这三个类来处理字符串,其中StringBuilder类是在JDK 1.5中新增的。
不同点如下:
1 是否有父类
String没有父类。
// String类不能被继承 // 实现了Serializable、Comparable和CharSequence(字符序列)接口 public final class String implements java.io.Serializable, Comparable<String>, CharSequence
StringBuilder和StringBuffer都继承了抽象类AbstractStringBuilder。
// 抽象类AbstractStringBuilder // 实现了Appendable(可追加)和CharSequence(字符序列)接口 abstract class AbstractStringBuilder implements Appendable, CharSequence
1 // StringBuilder类不能被继承 2 // 继承了抽象类AbstractStringBuilder 3 // 实现了Serializable和CharSequence接口 4 public final class StringBuilder 5 extends AbstractStringBuilder 6 implements java.io.Serializable, CharSequence
1 // StringBuffer类不能被继承 2 // 继承了抽象类AbstractStringBuilder 3 // 实现了Serializable和CharSequence接口 4 public final class StringBuffer 5 extends AbstractStringBuilder 6 implements java.io.Serializable, CharSequence
2 可变性
属性字符数组不可变(数组引用不可变,数组元素可变),String不可变,对于每个不同的字符串都需要一个单独的String对象。
// 字符数组 private final char value[];
AbstractStringBuilder中的字符数组可变,StringBuilder和StringBuffer可变。StringBuilder和StringBuffer都有insert()插入方法、delete()删除方法和append()末尾追加方法,调用System.arraycopy()方法来实现数组元素的拷贝。
// 字符数组 char[] value;
3 是否线程安全
String对象不可变,本质上是线程安全的。StringBuilder和StringBuffer的方法实现大致相同,不同之一是StringBuffer类的方法上加了synchronized关键字,即加了对象锁,该锁会锁住整个对象,效率低。也就是说,StringBuffer是线程安全的。
// 获取子串顺序下从某位置开始首次出现的位置 @Override public int indexOf(String str, int fromIndex) { return super.indexOf(str, fromIndex); }
@Override public synchronized int indexOf(String str, int fromIndex) { return super.indexOf(str, fromIndex); }
相同点如下:
1 substring()方法(截取字符串,即获取子串)
String中的substring()方法:
1 // 截取字符串 2 public String substring(int beginIndex, int endIndex) { 3 if (beginIndex < 0) { // 如果起始下标<0 4 throw new StringIndexOutOfBoundsException(beginIndex); 5 } 6 if (endIndex > value.length) { // 如果末尾下标>字符数组长度 7 throw new StringIndexOutOfBoundsException(endIndex); 8 } 9 int subLen = endIndex - beginIndex; // 获取截取长度 10 if (subLen < 0) { // 如果截取长度<0 11 throw new StringIndexOutOfBoundsException(subLen); 12 } 13 return ((beginIndex == 0) && (endIndex == value.length)) ? this 14 : new String(value, beginIndex, subLen); 15 }
AbstractStringBuilder中的substring()方法:
1 // 获取子串,返回String对象的引用 2 public String substring(int start, int end) { 3 if (start < 0) // 如果开始位置<0 4 throw new StringIndexOutOfBoundsException(start); 5 if (end > count) // 如果结束位置>count 6 throw new StringIndexOutOfBoundsException(end); 7 if (start > end) // 如果开始位置>结束位置 8 throw new StringIndexOutOfBoundsException(end - start); 9 // 返回String对象的引用 10 return new String(value, start, end - start); 11 }
substring()方法都是创建新的String对象并返回该对象引用。
总结
String适用于常量,StringBuilder适用于非并发情况下的字符串操作,StringBuffer适用于并发情况下的字符串操作。
参考资料
从Java源码角度彻底理解String,StringBuilder和StringBuffer的区别
《Effective Java 中文版 第2版》 P66-67
原文地址:https://www.cnblogs.com/WJQ2017/p/8409880.html