String,StringBuffer和StringBuilder

Posted perferect

tags:

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

  java 基础中字符串用到最多的就是String,StringBuffer和StringBuilder,这三个也是面试中最常问到的,三者之间的异同,其实实际工作中,我们大致知道使用场景,但是要用理论话的语言去总结,总是比较麻烦。

1.String

1.1继承实现关系

技术图片

1.2 源码分析

 1> final 修饰的类无法被继承

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence 

2> String的数据存放在final修饰的char数组中,所以String对象初始化之后值不能改

/** The value is used for character storage. */
    private final char value[];

3>String 值比较,总共两种方式,一种是继承了Comparable接口,实现compareTo()方法通过逐个字符串比较;

另一种方法是,compareToIgnoreCase() 方法,通过静态成员类,实现Comparator方法,逐个char变大写比较,变小写比较;

 public static final Comparator<String> CASE_INSENSITIVE_ORDER
                                         = new CaseInsensitiveComparator();
    private static class CaseInsensitiveComparator
            implements Comparator<String>, java.io.Serializable {
//。。。。。。

if (c1 != c2) {
    c1 = Character.toUpperCase(c1);
    c2 = Character.toUpperCase(c2);
    if (c1 != c2) {
        c1 = Character.toLowerCase(c1);
        c2 = Character.toLowerCase(c2);
        if (c1 != c2) {
            // No overflow because of numeric promotion
            return c1 - c2;
        }
    }
}
//。。。。。
}

 

 

4>字符串之间的关联,String提供了静态的方法,可以将多个字符串通过delimiter进行拼接;

public static String join(CharSequence delimiter, CharSequence... elements) {
}

5>字符串的trim()方法,对字符串双端去空

 public String trim() {
        int len = value.length;
        int st = 0;
        char[] val = value;    /* avoid getfield opcode */

        while ((st < len) && (val[st] <= ‘ ‘)) {
            st++;
        }
        while ((st < len) && (val[len - 1] <= ‘ ‘)) {
            len--;
        }
        return ((st > 0) || (len < value.length)) ? substring(st, len) : this;
    }

 

2.AbstractStringBuilder

2.1 继承实现关系  

技术图片

 

 

 

 2.2源码分析

1>初始长度设置,通过构造方法:数据存储在非fianl的char数组中,通过构造函数传参初始化;

  AbstractStringBuilder(int capacity) {
        value = new char[capacity];
    }

2>.在append的时候,char[]数组进行扩容,一般是现有值长度的2倍+2

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

private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        if (minimumCapacity - value.length > 0) {//最小长度大于现有长度时,进行扩容
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity));//复制生成新的char[]数组
        }
    }
private int newCapacity(int minCapacity) {
        // overflow-conscious code
        int newCapacity = (value.length << 1) + 2;//容量编程 现有长度的2倍+2
        if (newCapacity - minCapacity < 0) { //扩容后还是小于最小长度时,将最小长度赋值给扩容长度
            newCapacity = minCapacity;
        }
        return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
            ? hugeCapacity(minCapacity)
            : newCapacity;
    }

3.StringBuilder

1.源码分析

1>  final修饰的类,不可以继承

public final class StringBuilder
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence

2> 默认初始长度为16

public StringBuilder() {
        super(16);
    }
public StringBuilder(String str) {
super(str.length() + 16);
append(str);
}

3>转成字符串toString()方法是生成新的String对象

  @Override
    public String toString() {
        // Create a copy, don‘t share the array
        return new String(value, 0, count);
    }

4.StringBuffer

1.源码分析

1> final修饰不可继承

 public final class StringBuffer

2> toString缓存数据;

1.通过一个transient修饰的字段toStringCache,进行转字符串存储;

2.在每个值改变的操作将toStringCache设置为空;

3.在toString()方法中,如果toStringCache为空,就copy新的char[]数组赋值给toStringCache ;

4.如果StringBuffer中的数值没变动,调用toString方法的时候,直接调用toStringCache就可以了;

private transient char[] toStringCache;
@Override
public synchronized StringBuffer append(long lng) {
   toStringCache = null;
   super.append(lng);
   return this;
}
@Override
public synchronized String toString() {
   if (toStringCache == null) {
      toStringCache = Arrays.copyOfRange(value, 0, count);
   }
   return new String(toStringCache, true);
}

  

通过上面的可以知道,如下:

相同点:

1.都是final类,不可以继承;

2.内部存取数据的都是char数组;

3.都实现了CharSequeue,可以对字符串进行相关操作;

不同点:

1.String 和StringBuilder,StringBuffer的区别:

  - 1. String的值final 数组,赋值后不可改变;StringBuilder,StringBuffer 非final  char数组,初始化后可以改变值;

  - 2. String的字符拼接,每拼接一次,相当于生成一个新的字符串;StringBuilder,StringBuffer通过给内部的char数组扩容,不用生成新的对象,效率更高;

2.StringBuilder 和 StringBuffer 之间的区别:

  - 1. StringBuffer的所有操作都加synchorinized

  - 2. StringBuffer的toString方法,有缓存,多次toString效率更高;

  - 3.StringBuilder 效率更高,但是线程不安全;

 

常见问题:

 1.自己写一个String,或StringBuilder类可以替换原有的JDK的String么?

    答:这个问题其实和String,StringBuilder没关系了,而涉及到的是JVM类加载中,双亲委派模型;

   双亲委派模型,是类加载器接收到当前类的加载请求,并不会直接去加载,而是逐级向父加载器发送请求,当父加载器没有相关的类,当前子加载器才自行加载;

  

 

 

 

 

 

  

  

  

 

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

(转)String,StringBuffer与StringBuilder的区别

Java常用类--String类(StringBuilder 和 StringBuffer)介绍

StringBuffer和StringBuilder类

Java String, StringBuilder, StringBuffer

Java StringStringBuilderStringBuffer[笔记]

重温java中的String,StringBuffer,StringBuilder类