String存放在堆中還是棧中
先定義S
String str1 = "abc";
System.out.println(str1 == "abc");
步驟:
1) 棧中開辟一塊空間存放引用str1浇借,
2) String池中開辟一塊空間作喘,存放String常量"abc",
3) 引用str1指向池中String常量"abc",
4) str1所指代的地址即常量"abc"所在地址哥攘,輸出為true
2. String str2 = new String("abc");
? System.out.println(str2 == "abc");
步驟:
1) 棧中開辟一塊空間存放引用str2,
2) 堆中開辟一塊空間存放一個(gè)新建的String對象"abc"猪勇,
3) 引用str2指向堆中的新建的String對象"abc"溜族,
4) str2所指代的對象地址為堆中地址,而常量"abc"地址在池中挤悉,輸出為false
3. String str3 = new String("abc");
? System.out.println(str3 == str2);
步驟:
1) 棧中開辟一塊空間存放引用str3渐裸,
2) 堆中開辟一塊新空間存放另外一個(gè)(不同于str2所指)新建的String對象,
3) 引用str3指向另外新建的那個(gè)String對象
4) str3和str2指向堆中不同的String對象装悲,地址也不相同昏鹃,輸出為false
4. String str4 = "a" + "b";
? System.out.println(str4 == "ab");
步驟:
1) 棧中開辟一塊空間存放引用str4,
2) 根據(jù)編譯器合并已知量的優(yōu)化功能诀诊,池中開辟一塊空間洞渤,存放合并后的String常量"ab",
3) 引用str4指向池中常量"ab"属瓣,
4) str4所指即池中常量"ab"载迄,輸出為true
注:編譯器合并已知量的優(yōu)化功能解釋---
原理1:當(dāng)使用任何方式來創(chuàng)建一個(gè)字符串對象s=X時(shí),Java運(yùn)行時(shí)(運(yùn)行中JVM)會拿著這個(gè)X在String池中找是否存在內(nèi)容相同的字符串對象抡蛙,如果不存在护昧,則在池中創(chuàng)建一個(gè)字符串s,否則粗截,不在池中添加惋耙。
原理2:Java中,只要使用new關(guān)鍵字來創(chuàng)建對象,則一定會(在堆區(qū)或棧區(qū))創(chuàng)建一個(gè)新的對象绽榛。
原理3:使用直接指定或者使用純字符串串聯(lián)來創(chuàng)建String對象遥金,則僅僅會檢查維護(hù)String池中的字符串,池中沒有就在池中創(chuàng)建一個(gè)蒜田,有則罷了稿械!但絕不會在堆棧區(qū)再去創(chuàng)建該String對象。
原理4:使用包含變量的表達(dá)式來創(chuàng)建String對象冲粤,則不僅會檢查維護(hù)String池美莫,而且還會在堆棧區(qū)創(chuàng)建一個(gè)String對象。
5. final String s = "a";
? String str5 = s + "b";
? System.out.println(str5 == "ab");
步驟:
同4? 注:s用了final進(jìn)行了修飾 所以不適用于原理4? 當(dāng)不用final? 適用于原理4 輸出為false
6. String s1 = "a";
? String s2 = "b";
? String str6 = s1 + s2;
? System.out.println(str6 == "ab");
步驟:
1) 棧中開辟一塊中間存放引用s1梯捕,s1指向池中String常量"a"厢呵,
2) 棧中開辟一塊中間存放引用s2,s2指向池中String常量"b"傀顾,
3) 棧中開辟一塊中間存放引用str6襟铭,
4) s1 + s2通過StringBuilder的最后一步toString()方法還原一個(gè)新的String對象"ab",因此堆中開辟一塊空間存放此對象短曾,
5) 引用str6指向堆中(s1 + s2)所還原的新String對象寒砖,
6) str6指向的對象在堆中,而常量"ab"在池中嫉拐,輸出為false
7. String str7 = "abc".substring(0, 2);
步驟:
1) 棧中開辟一塊空間存放引用str7哩都,
2) substring()方法還原一個(gè)新的String對象"ab"(不同于str6所指),堆中開辟一塊空間存放此對象婉徘,
3) 引用str7指向堆中的新String對象漠嵌,
8. String str8 = "abc".toUpperCase();
步驟:
1) 棧中開辟一塊空間存放引用str6,
2) toUpperCase()方法還原一個(gè)新的String對象"ABC"盖呼,池中并未開辟新的空間存放String常量"ABC"儒鹿,
3) 引用str8指向堆中的新String對象