JDK源码分析系列---String,StringBuilder,StringBuffer
1.String
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { //存储字符,final修饰 private final char value[]; //缓存hash code,默认0 private int hash; //序列号 private static final long serialVersionUID = -6849794470754667710L; //声明可序列化字段 private static final ObjectStreamField[] serialPersistentFields = new ObjectStreamField[0]; }
1.1 基本属性
- char value[],用来存储字符串对象的字符数组
- int hash,用来缓存字符串的hash code,默认值为0
- long serialVersionUID,用来序列化的序列版本号
- ObjectStreamField[],可序列化类的字段说明
1.2 常用构造器
public String() { this.value = "".value; }
初始化新创建的对象,表示空字符串""。请注意,此构造函数是不需要使用的,因为字符串是不可变的
String str = new String(); 本质上是创建了一个空的字符数组,str的长度为0
public String(String original) { this.value = original.value; this.hash = original.hash; }
初始化新创建的对象,表示和参数一样的字符串,换句话说是创建了和参数一样的对象副本,除非需要显示的声明副本,否则该构造函数是不需要的,因为字符串是不可变的
public String(StringBuffer buffer) { synchronized(buffer) { this.value = Arrays.copyOf(buffer.getValue(), buffer.length()); } }
把StringBuffer的内容复制到String对象中,随后修改StringBuffer对象的值,并不会影响String对象
public String(StringBuilder builder) { this.value = Arrays.copyOf(builder.getValue(), builder.length()); }
把StringBuilder的内容复制到String对象中,随后修改StringBuilder的值,并不会影响String对象;
此构造函数是为了把StringBuilder转移到String对象,但是推荐使用StringBuilder的toString()方法,因为运行更快
1.3 常用方法
//返回字符串的长度 public int length() { return value.length; } //比较两个String值是否相等 public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String)anObject; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; } //生成hash code public int hashCode() { int h = hash; if (h == 0 && value.length > 0) { char val[] = value; for (int i = 0; i < value.length; i++) { h = 31 * h + val[i]; } hash = h; } return h; }
equals方法的判断流程:
- 首先判断两个对象是否相同,若相同返回true;若不同,下一步
- 判断参数是否为String对象,若不是,返回false;若是,下一步
- 判断两个String的长度是否相等,若不是,返回false;若是,下一步
- 按字符数组索引依次比较字符,如果有任一不相同,返回false,否则返回true
1.2 为什么说String是不可变对象?
- 存储字符的数组value[]是final修饰的,值不可更改.
2. AbstractStringBuilder
可变的字符序列,StringBuilder和StringBuffer都继承了该类,要了解StringBuilder和StringBuffer首先先了解AbstractStringBuilder.
2.1 基本属性
abstract class AbstractStringBuilder implements Appendable, CharSequence { /** * The value is used for character storage. */ char[] value; /** * The count is the number of characters used. */ int count; }
- char[] value:存储字符的数组
- int count:使用的字符的数量
2.2 构造器
/** * 无参构造器,用于子类序列化 */ AbstractStringBuilder() { } /** * 指定字符数组容量 */ AbstractStringBuilder(int capacity) { value = new char[capacity]; }
2.3 常用方法
/** * 返回字符的数量 */ @Override public int length() { return count; } /** * 返回当前可存储字符的最大数量,即容量 */ public int capacity() { return value.length; } /** * 保证当前容量大于等于指定的最小数量minimumCapacity,会调用扩容方法 */ public void ensureCapacity(int minimumCapacity) { if (minimumCapacity > 0) ensureCapacityInternal(minimumCapacity); } /** * 扩容,只有minimumCapacity大于当前容量,才会copy数组扩容 */ private void ensureCapacityInternal(int minimumCapacity) { // overflow-conscious code if (minimumCapacity - value.length > 0) { value = Arrays.copyOf(value, newCapacity(minimumCapacity)); } } /** * 当前对象拼接字符串str * 如果参数为null,那么最终字符串为"null",如果参数类型为boolean,那么返回的是"true"或"false" * 例1: "abc".append(null) = "abcnull" * 例2: "abc".append("def") = "abcdef" */ public AbstractStringBuilder append(String str) { if (str == null) return appendNull(); int len = str.length(); ensureCapacityInternal(count + len); str.getChars(0, len, value, count); count += len; return this; }
3. StringBuilder
可变的字符序列,非线程安全,StringBuilder和StringBuffer的实现方法很相似,区别在于是否线程安全,在单线程的情况下可使用StringBuilder,因为它比StringBuffer运行更快.StringBuilder继承了AbstractStringBuilder类.
3.1 基本属性
继承父类
3.2 构造器
public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence{ /** *序列号 */ static final long serialVersionUID = 4383685877147921099L; /** * 默认容量16 * initial capacity of 16 characters. */ public StringBuilder() { super(16); } /** * 指定初始容量 */ public StringBuilder(int capacity) { super(capacity); } /** * 把String字符串初始化到对象中,容量变为str的长度+16 */ public StringBuilder(String str) { super(str.length() + 16); append(str); } /** * 把字符初始化到对象中,容量变为字符的长度+16 */ public StringBuilder(CharSequence seq) { this(seq.length() + 16); append(seq); }
3.3 常用方法
同父类
4. StringBuffer
可变的字符序列,线程安全,.StringBuffer继承了AbstractStringBuilder类.
4.1 基本属性
继承父类,同时还有以下属性
public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence{ /** * 最后一次调用toString返回值的缓存 * 当StringBuffer被修改时该缓存被清除 */ private transient char[] toStringCache; /** 序列号 */ static final long serialVersionUID = 3388685877147921107L; }
4.2 构造器
同StringBuilder
4.3 常用方法
与StringBuilder方法基本相同,唯一区别在于在StringBuilder的方法上加了synchronized锁.
5.总结
综上所述,可以得出相同点是:都可以创建字符串,不同在于String是不可变的,不存在线程安全问题;StringBuilder和StringBuffer字符串是可变的,StringBuilder线程不安全,适合单线程使用,StringBuffer线程安全,适合多线程;对于频繁需要字符串的拼接操作时,不建议使用String,因为每次都需要创建一个String对象.
- JDK源码分析之String、StringBuilder和StringBuffer
- String、StringBuilder、 StringBuffer 深入分析 源码解析
- JDK源码解析基础篇-String、StringBuilder、StringBuffer
- 深入java String拼接和StringBuffer、StringBuilder(分析源码)
- String、StringBuilder、 StringBuffer 深入分析 源码解析
- String,StringBuffer和StringBuilder源码解析[基于JDK6]
- String、StringBuffer、StringBuilder源码分析
- 【JDK源码分析】StringBuffer与StringBuilder
- java学习之旅57、58--数组_StringBuilder和StringBuffer的使用_JDK源码分析内部机制、常用方法补充_常见面试题答法
- 56-58_数组_StringBuilder和StringBuffer_常用方法_方法链的实现_JDK源码分析_常见面试题
- String、StringBuilder与StringBuffer源码分析
- JDK源码之String、StringBuffer、StringBuilder
- 通过源码分析String、StringBuffer和StringBuilder
- JDK 1.7源码阅读笔记(一)String,StringBuilder,StringBuffer
- 【Java】从源码角度分析String,StringBuffer和StringBuilder
- 【JDK】:java.lang.String、StringBuilder、StringBuffer 源码解析
- java学习之旅56--数组_StringBuilder和StringBuffer的使用_常用方法_方法链的实现_JDK源码分析
- 大数据学习--day14(String--StringBuffer--StringBuilder 源码分析、性能比较)
- JDK1.8源码阅读之——String,StringBuffer, StringBuilder
- jdk类库源码分析-StringBuffer、StringBuilder