String StringBuilder和StringBuffer 结合源码解析
String StringBuilder和StringBuffer 结合源码解析
一、String
当我们在对字符串进行操作的时候,就会使用到String、StringBuilder和StringBuffer,然后在使用的时候我们还要注意三者的区别。
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,其引用没有变化。
1 String s = "abc"; 2 char data[] = {'a', 'b', 'c'}; 3 String str = new String(data); 4 System.out.println(str);//abc 5 System.out.println(str.length());//长度为3其实,String的内部是个数组, 6 //源码如下: 7 /** 8 * Allocates a new {@code String} so that it represents the sequence of 9 * characters currently contained in the character array argument. The 10 * contents of the character array are copied; subsequent modification of 11 * the character array does not affect the newly created string. 12 * 13 * @param value 14 * The initial value of the string 15 */ 16 public String(char value[]) { 17 this.value = Arrays.copyOf(value, value.length); 18 } 19 //那么为什么String类型的变量是不可变的呢?从源码中解析: 20 /** The value is used for character storage. */ 21 private final char value[]; 22 23 /** Cache the hash code for the string */ 24 private int hash; // Default to 0 25 //这两个属性其中char是final的,也是不可变的,private类型,其中,在String中没有两//个属性的get、set方法,既无法去设置String的值,因此是无法改变的。
二、StringBuilder
源码中:
1 public final class StringBuilder 2 extends AbstractStringBuilder 3 implements java.io.Serializable, CharSequence{}//你会发现fianl的,既不可继承的。 4 /** 5 * Constructs a string builder with no characters in it and an 6 * initial capacity of 16 characters. 7 */ 8 public StringBuilder() { 9 super(16); 10 }//当你创建了一个StringBuilder的时候,其长度默认为16。 11 /** 12 * Constructs a string builder initialized to the contents of the 13 * specified string. The initial capacity of the string builder is 14 * <code>16</code> plus the length of the string argument. 15 * 16 * @param str the initial contents of the buffer. 17 * @throws NullPointerException if <code>str</code> is <code>null</code> 18 */ 19 public StringBuilder(String str) { 20 super(str.length() + 16); 21 append(str); 22 } 23 //如果长度大于了16,StringBuilder会在16的基础上进行扩容。/** 24 * Constructs a string builder with no characters in it and an 25 * initial capacity specified by the <code>capacity</code> argument. 26 * 27 * @param capacity the initial capacity. 28 * @throws NegativeArraySizeException if the <code>capacity</code> 29 * argument is less than <code>0</code>. 30 */ 31 public StringBuilder(int capacity) { 32 super(capacity); 33 } 34 //你也可以自定义长度,但是长度不能小于0,否则会NegativeArraySizeException异常。 public StringBuilder append(boolean b) { 35 super.append(b); 36 return this; 37 } 38 39 public StringBuilder append(char c) { 40 super.append(c); 41 return this; 42 } 43 44 public StringBuilder append(int i) { 45 super.append(i); 46 return this; 47 } 48 49 public StringBuilder append(long lng) { 50 super.append(lng); 51 return this; 52 } 53 54 public StringBuilder append(float f) { 55 super.append(f); 56 return this; 57 } 58 59 public StringBuilder append(double d) { 60 super.append(d); 61 return this; 62 }
另外,你会发现StringBuilder不是线程安全的,所谓的线程安全就是在多线程的情况下,会出现多个多个append同时修改导致的结果不一致的不安全问题,因此如果要多线程使用StringBuilder的时候,要自己实现锁的问题。建议在单线程下使用StringBuilder。
三、StringBuffer
public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence{}
StringBuffer与StringBuilder在实现功能上市类似的,其主要区别在于,StringBuffer是线程安全的,StringBuffer也是final的,不可继承的。并且是可变的,使用synchronized使线程安全了。
1 public synchronized StringBuffer append(Object obj) { 2 super.append(String.valueOf(obj)); 3 return this; 4 } 5 6 public synchronized StringBuffer append(String str) { 7 super.append(str); 8 return this; 9 }public synchronized StringBuffer append(boolean b) { 10 super.append(b); 11 return this; 12 } 13 14 public synchronized StringBuffer append(char c) { 15 super.append(c); 16 return this; 17 } 18 19 public synchronized StringBuffer append(int i) { 20 super.append(i); 21 return this; 22 }
四、总结:
(1)String类型是被final修饰的,长度不可变的,即使使用concat方法,也是新创建了个对象,将值赋给了新的对象。
(2)StringBuilder是长度可变的,可以使用append方法增加长度,默认长度为16,但是线程不安全,速度快。
(3)StringBuffer是长度可变的,可以使用append方法增加长度,默认长度为16,是线程安全的,因为使用了所锁的作用,与StringBuilder相比的速度比较慢。
如有错误,请多多指教,谢谢,博主会再接再厉,写出更好的文章。