一、String
以下幾個特性決定它是不可變的
1、`String`是`final`類,不可繼承。
2、字符數組成員變量`value`使用`final`修飾,也就是常量,常量一大好處就是線程安全,所以`String`不需要考慮線程安全問題。
3、通過反射還是可以修改value
常量值的,這時候會發現如果字符串是在常量池裏,那麼這個常量池字符串將會被修改成其他值。
4、成員變量`value`字符數組必須獨有,其他程序(不包括String類和反射)不可操作`value`字符數組
二、String 構造器
/**
*創建空的字符串數組
*/
public String() {
this.value = "".value;
}
//新創建的字符串是參數字符串的副本。不需要,因爲字符串是不可變的。
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
//根據數組創建字符串(方式一)
//傳入一個字符數組,將該數組拷貝一份複製給value,其實這樣做就是爲了保證String不可變性
public String(char value[]) {
this.value = Arrays.copyOf(value, value.length);
}
//根據數組創建字符串(方式二)
//取得傳入字符數組的部分元素,在第一種情況下,就是多了對傳入的offset count變量判斷是否下標越界
public String(char value[], int offset, int count) {
if (offset < 0) {
throw new StringIndexOutOfBoundsException(offset);
}
if (count <= 0) {
if (count < 0) {
throw new StringIndexOutOfBoundsException(count);
}
if (offset <= value.length) {
this.value = "".value;
return;
}
}
// Note: offset or count might be near -1>>>1.
if (offset > value.length - count) {
throw new StringIndexOutOfBoundsException(offset + count);
}
this.value = Arrays.copyOfRange(value, offset, offset+count);
}
//根據數組創建字符串(方式三)
//bytes:需要轉換成字符串的字節數組
//offset:字節數組的第一個字節的下標
//length:需要轉換成字符串的字節長度=
//charsetName:編碼格式的字符串名稱,如:UTF-8
//charset:編碼格式java.nio.charset.Charset,如:Charset.forName("UTF-8");
public String(byte bytes[], int offset, int length, Charset charset) {
if (charset == null)
throw new NullPointerException("charset");
checkBounds(bytes, offset, length);
this.value = StringCoding.decode(charset, bytes, offset, length);
}
三、String(StringBuffer buffer)和public String(StringBuilder builder)
public String(StringBuffer buffer) {
synchronized(buffer) {
this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
}
}
public String(StringBuilder builder) {
this.value = Arrays.copyOf(builder.getValue(), builder.length());
}
從源碼可知,是複製數組然後賦值
四、String.intern() 這是重點
1、字符串常量池,初始是空的,它是由String類私自維護的。
2、當intern方法調用,如果常量池中存在這個字符串(由equals方法判斷相等的),則返回常量池中的字符串,否則將這個字符串添加到常量池中,並返回一個對這個對象的引用。
其實就是存在則返回,否則添加並返回。
由此可見,對於任意兩個字符串s和t,s.intern() == t.intern() 是 true,s.equals(t) 也是 true。
3、所有的字符串和字符串值的常數表達式都被插入 ,字符串字面量是在 Java™語言規範的3.10.5. String 字面量中定義的,關於字面
char[] value = {'1','a','2','b'};
String str = "1a2b";//常量池中創建
String s = new String(value);//在堆中創建String對象
String intern = s.intern();//從常量池中獲取
System.out.println(str==s);//false
System.out.println(str==intern);//true
System.out.println(s==intern);//false
五、字符串拼接
方式一:
String a = "123"+"456";
//這種方式的拼接在class編譯後變成
String a = "123456";
方式二:
public void appen(String a) {
String a = a + "124";
}
//這種編譯後在class中是使用StringBuilder的append()拼接
new StringBuilder().append(a).append("124").toString();
//原理可去查看我的語法糖博客
如有疏漏之處,請各位斧正;