轉自:https://blog.csdn.net/wxz980927155/article/details/81712342
?
起因
再一次js的json對象的比較中,發現相同內容的json對象使用==比較并不相等。?
例如:
var obj = {};
var obj2 = {};
console.log(obj == obj2); // 結果為false
json在js中代表一個對象==比較的是對象棧中存放引用堆的地址。上面的obj和obj2創建的是兩個對象地址肯定不同結果為false。
但最令我不解的是為什么js的字符串比較可以用==來比較字符串的內容是否相等,而java卻要使用equals去比較字符串的內容是否相等。但當我發現下面代碼的時候又刷新了我這個菜鳥的認知。
String str1 = "test";
String str2 = "test";
System.out.println(str1 == str2); // 結果為true
?
結果難道不該為false嗎?字符串的比較難道不是用equals來比較內容是否相等嗎?兩個不同的對象創建的內存地址應該是不一樣的啊!!后來經過網上查閱資料發現jvm還存在一個字符串常量池。
字符串常量池
讓我們先分析一下上述的代碼:
在我的理解中常量池應該是為了減少開發者對字符串過度的創建,導致內存使用率的提升,畢竟String類是一個final類,操作字符串永遠不會改變當前字符串的值,只會新增一個字符串對象。
String str1 = "test";
/* jvm在編譯的時候會先查看str1字面量test是否存放在字符串常量池中有則直
接引用字符串常量池里面的地址,沒有則在字符串常量池新創建一個*/
String str2 = "test"; /* str2發現字符串常量池里面已經有了test則直接把字符串常量池里面的地址拿 了過來*/ System.out.println(str1 == str2); // 最終str1和str2的地址都是相同的結果肯定為true啦
既然都到這里在拓展拓展在走唄
String str1 = new String("test");
String str2 = new String("test"); System.out.println(str1 == str2); // 結果為false // 這個為什么不為true了呢?
new String()會在代碼運行的時候在堆中開辟一個空間存放引用字符串常量池里面的地址但是棧里面引用的堆的地址是不一樣的,所以即使引用的字符串常量池里面的地址是一樣也永遠不可能為true!!?
intern方法
強制String對象使用字符串常量池
String str1 = new String("test");
String str2 = new String("test"); str1 = str1.intern(); str2 = str2.intern(); System.out.println(str1 == str2); // 結果為true
?
經典面試題
String str1 = new String("test");
// 此代碼執行會創建幾個對象? // A:1個或2個,堆中會創建一個,字符串常量池中有test則常量池中不會創建,沒有則創建
總結
-
字符串字面量會在編譯的就開始判斷是否在字符串常量池里面創建,而new String()會在代碼運行的時候才去判斷。
-
字符串常量池里面沒有此字符串則會創建,有則會去引用字符串常量池里面的字符串。字面量里字符串常量池的地址存放在棧中,new String()則存放在堆中。