String StringBuilder和StringBuffer 结合源码解析
当我们在对字符串进行操作的时候,就会使用到String、StringBuilder和StringBuffer,然后在使用的时候我们还要注意三者的区别。
一、String
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {}
在String的源码中,String的类是final的,因此该类是不能被继承的,那么为什么String类型的变量是不允许改变的呢,初学经常误认为是变化了的,其实不然,事实上是final在修饰基本类型的时候,是其变量的值不可变;修饰引用对象的时候,是其引用不可变,其对象的内容可变。
例如:String sb = "abc"; sb = "abcd";sb变量会存入到jvm的栈内存中,只是sb刚开始的时候,是指向的abc,后面又指向了abcd,其引用没有变化。String s = "abc"; char data[] = {'a', 'b', 'c'}; String str = new String(data); System.out.println(str);//abc System.out.println(str.length());//长度为3其实,String的内部是个数组,源码如下:/** * Allocates a new {@code String} so that it represents the sequence of * characters currently contained in the character array argument. The * contents of the character array are copied; subsequent modification of * the character array does not affect the newly created string. * * @param value * The initial value of the string */ public String(char value[]) { this.value = Arrays.copyOf(value, value.length); }那么为什么String类型的变量是不可变的呢?从源码中解析:/** The value is used for character storage. */ private final char value[]; /** Cache the hash code for the string */ private int hash; // Default to 0这两个属性其中char是final的,也是不可变的,private类型,其中,在String中没有两个属性的get、set方法,既无法去设置String的值,因此是无法改变的。二、StringBuilder
源码中:
public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence{}你会发现fianl的,既不可继承的。/** * Constructs a string builder with no characters in it and an * initial capacity of 16 characters. */ public StringBuilder() { super(16); }当你创建了一个StringBuilder的时候,其长度默认为16,如果长度大于了16,/** * Constructs a string builder initialized to the contents of the * specified string. The initial capacity of the string builder is * <code>16</code> plus the length of the string argument. * * @param str the initial contents of the buffer. * @throws NullPointerException if <code>str</code> is <code>null</code> */ public StringBuilder(String str) { super(str.length() + 16); append(str); }StringBuilder会在16的基础上进行扩容。/** * Constructs a string builder with no characters in it and an * initial capacity specified by the <code>capacity</code> argument. * * @param capacity the initial capacity. * @throws NegativeArraySizeException if the <code>capacity</code> * argument is less than <code>0</code>. */ public StringBuilder(int capacity) { super(capacity); }你也可以自定义长度,但是长度不能小于0,否则会NegativeArraySizeException异常。public StringBuilder append(boolean b) { super.append(b); return this; } public StringBuilder append(char c) { super.append(c); return this; } public StringBuilder append(int i) { super.append(i); return this; } public StringBuilder append(long lng) { super.append(lng); return this; } public StringBuilder append(float f) { super.append(f); return this; } public StringBuilder append(double d) { super.append(d); return this; }另外,你会发现StringBuilder不是线程安全的,所谓的线程安全就是在多线程的情况下,会出现多个多个append同时修改导致的结果不一致的不安全问题,因此如果要多线程使用StringBuilder的时候,要自己实现锁的问题。建议在单线程下使用StringBuilder。三、StringBuffer
public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence{}StringBuffer与StringBuilder在实现功能上市类似的,其主要区别在于,StringBuffer是线程安全的,StringBuffer也是final的,不可继承的。并且是可变的,使用synchronized使线程安全了。public synchronized StringBuffer append(Object obj) { super.append(String.valueOf(obj)); return this; } public synchronized StringBuffer append(String str) { super.append(str); return this; }public synchronized StringBuffer append(boolean b) { super.append(b); return this; } public synchronized StringBuffer append(char c) { super.append(c); return this; } public synchronized StringBuffer append(int i) { super.append(i); return this; }四、总结:
(1)String类型是被final修饰的,长度不可变的,即使使用concat方法,也是新创建了个对象,将值赋给了新的对象。
(2)StringBuilder是长度可变的,可以使用append方法增加长度,默认长度为16,但是线程不安全,速度快。(2)StringBuffer是长度可变的,可以使用append方法增加长度,默认长度为16,是线程安全的,因为使用了所锁的作用,与StringBuilder相比的速度比较慢。如有错误,请多多指教,谢谢,博主会再接再厉,写出更好的文章。