下面代碼:
public class Test1 {
public static void main(String[] args) {
String str1="hello";
String str3="hello word!";
String str4=str1+"word!";
System.out.println(str3==str4);//false
}
}
結果爲:
String str3=“hello word!”;此句執行完之後,會將str3放入常量池;
String str4=str1+“word!”;結果也是 hello world,爲什麼str3==str4的結果爲:false;
按照String對象創建的原理,str4是採用直接賦值的方法創建的,不是應該複用常量池中的str3的對象嗎,結果不應該是true嗎,但爲什麼是false呢?
(1) String的“+”拼接字符串,其真正實現的原理是中間通過建立臨時的StringBuilder對象,然後調用append方法實現,然後再調用StringBuilder對象的toString方法將該StringBuilder對象轉化爲String對象,但StringBuilder對象的toString方法中是新new了一個String對象;
(2) String str4=str1+“word!”;語句執行過程爲:創建一個StringBuilder對象,比如sb,然後調用append方法,sb.append(str1)和sb.append(“world!”);此時sb的值爲:“hello word!”,然後再調用toString方法,通過觀察源碼
public String toString() {
// Create a copy, don't share the array
return new String(value, 0, count);
}
可以發現:StringBuilder對象的toString方法中是新new了一個String對象,所以str4是指向一個使用new新創建出來的一個對象,不會複用常量池中的對象;
所以str3的地址是和str4的地址不同的,所以結果爲false;
觀察另外一段代碼,在查找資料時碰巧遇到的,就順便學習了一下:
public class Test1 {
public static void main(String[] args) {
String str1 = null;
String str2 = "hello";
String str = str1 + str2;
System.out.println(str);//nullhello
}
}
通過運行可知結果爲:nullhello
爲什麼呢?
通過觀察源碼:
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 AbstractStringBuilder appendNull() {
int c = count;
ensureCapacityInternal(c + 4);
final char[] value = this.value;//在源碼中可找到 char[] value爲空
value[c++] = 'n';
value[c++] = 'u';
value[c++] = 'l';
value[c++] = 'l';
count = c;
return this;
}
可知,如果str=null,sb.append(str)會返回一個null;
所以該段代碼的結果爲:null222222