JDK 1.8 源码解析 StringStringBuilder和StringBuffer的异同

Posted wjq2017

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDK 1.8 源码解析 StringStringBuilder和StringBuffer的异同相关的知识,希望对你有一定的参考价值。

  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

以上是关于JDK 1.8 源码解析 StringStringBuilder和StringBuffer的异同的主要内容,如果未能解决你的问题,请参考以下文章

JDK 1.8 源码解析 HashSet

JDK 1.8 源码解析 ConcurrentHashMap

JDK 1.8 源码解析 StringStringBuilder和StringBuffer的异同

Java深入研究9HashMap源码解析(jdk 1.8)

JDK1.8JDK1.8集合源码阅读——TreeMap

Objects源码解析