JDK源码之String,StringBuffer,StringBuilder

Posted 架构探索

tags:

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

前言  

最近公司招聘Java开发人员,面试时会问一些jdk源码相关的问题,如String相关,但很少有答得全面的,今天总结一下,供学习参考


String,StringBuffer,StringBuilder之间的对比:


总结:

  • 三者的继承结构(这里忽略了Serializable)


  • StringBuffer与StringBuilder两者之间的主要区别 

       (1)线程安全性,StringBuffer是线程安全的,而StringBuilder是线程非安全的,也因此在速度上, StringBuilder优于StringBuffer    

   (2)还有一点,StringBuffer内部有针对toString()的cache, 字段名toStringCache,StringBuffer每次操作都会将toStringCache设置为null


  • 性能,速度

    大多数情况下:StringBuilder > StringBuffer > String

    单字符串操作时, String最佳, 如下:

String s1 = "abc";StringBuilder s2 = new StringBuilder().append("abc");


  • 使用哪一个


    有大量字符串拼接或修改时, 单线程环境下用StringBuilder, 多线程环境下用StringBuffer, 若使用String进行大量字符拼接操作, 则会产生大量垃圾对象,浪费系统资源并且会影响系统性能

    不涉及字符拼接以及更改时,直接使用String最佳


源码赏析:

  • StringBuffer与StringBuilder序列化的实现

StringBuffer的实现:private synchronized void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { java.io.ObjectOutputStream.PutField fields = s.putFields(); fields.put("value", value); fields.put("count", count); fields.put("shared", false); s.writeFields();}
private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { java.io.ObjectInputStream.GetField fields = s.readFields(); value = (char[])fields.get("value", null); count = fields.get("count", 0);}
StringBuilder的实现:private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { s.defaultWriteObject(); s.writeInt(count); s.writeObject(value);}
private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { s.defaultReadObject(); count = s.readInt(); value = (char[]) s.readObject();}
  • StringBuffer与StringBuilder的扩容检测及实现

AbstractStringBuilder类中的方法//扩容检测private void ensureCapacityInternal(int minimumCapacity) { //数组长度不够容纳新元素时,进行扩容 if (minimumCapacity - value.length > 0) expandCapacity(minimumCapacity);}
//扩容实现void expandCapacity(int minimumCapacity) { int newCapacity = value.length * 2 + 2; if (newCapacity - minimumCapacity < 0) newCapacity = minimumCapacity; if (newCapacity < 0) { if (minimumCapacity < 0) // overflow throw new OutOfMemoryError(); newCapacity = Integer.MAX_VALUE; } //开辟一个新数组, 并且原数组的元素复制过去 value = Arrays.copyOf(value, newCapacity);}
  • String类重写的hashCode方法实现

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;}

以上是关于JDK源码之String,StringBuffer,StringBuilder的主要内容,如果未能解决你的问题,请参考以下文章

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

jdk 源码系列之StringBuilderStringBuffer

String stringbuffer StringBuilder

java基础之结合源码理解字符串类的重要知识点

java基础之结合源码理解字符串类的重要知识点

java基础之结合源码理解字符串类的重要知识点