字符串一旦生成就不能改變。
image.png
字符串本身在堆中,而字符串常量池中有指向他的引用袱结,字符串常量池也在堆中亮隙!
當(dāng)字面量方式聲明時(shí),查找常量池垢夹,有則返回引用溢吻,沒有就在堆中生成對(duì)象,同時(shí)在常量池中生成引用果元,如:String s = "xyz";
字面量相加促王,根據(jù)+的結(jié)果查找常量池,有則返回引用噪漾,沒有則堆內(nèi)生成對(duì)象硼砰,同時(shí)常量池中產(chǎn)生引用,在這里final 的變量欣硼,也看成字面量
字符串相加题翰,如果相加時(shí)不是字面量,那么就要在堆中生成新的對(duì)象诈胜,常量池中不生成引用豹障,String s = s1 + "abc"; --> String s = new String(s1 +"abc");
image.png
final String s1 = "a";
String s2 = "a"+"b";
String s3 = "ab"
String s4 = "ab";
System.out.println((s1+"b") == s3); true, 這里由于final string的緣故,所以a+2是兩個(gè)常量焦匈,會(huì)在編譯的時(shí)候直接折疊成一個(gè)字符串常量血公,他們都存在于字符串常量池中
System.out.println(s3 == s2); true, s2由兩個(gè)常量組成,這里也折疊了
System.out.println(s3 == s4); true
String str = "a" + "b" + "c"; 根據(jù)折疊原理缓熟,這里只創(chuàng)建了一個(gè)對(duì)象
public class Demo {
public static void main(String[] args) {
String str1="abc"; // 使用字符串常量累魔,從字符串常量池中取
String str2="abc";
String str3=new String("abc"); // new創(chuàng)建一個(gè)新對(duì)象,str3指向堆內(nèi)存够滑,str1指向常量池
String str4=new String("abc");
String str5=str4.intern(); // **intern "返回一個(gè)常量池中的固定對(duì)象垦写。當(dāng)intern方法被調(diào)用時(shí),如果常量池中已經(jīng)包含了這個(gè)String對(duì)象(用equals方法判斷包含與否)彰触,那么直接返回這個(gè)對(duì)象梯投。否則,就向常量中添加這個(gè)對(duì)象况毅,并返回對(duì)它的引用"**
System.out.println(str1==str2);//第一行分蓖,true
System.out.println(str1==str3);//第二行,false
System.out.println(str1==str5);//第三行尔许,true
System.out.println(str3==str4);//第四行么鹤,false
System.out.println(str3==str5);//第五行,false
System.out.println(str1.equals(str2));//第六行母债,true
System.out.println(str1.equals(str3));//第七行午磁,true
System.out.println(str1.equals(str5));//第八行尝抖,true
System.out.println(str3.equals(str4));//第九行,true
System.out.println(str3.equals(str5));//第十行迅皇,true
}
}
class internDemo
{
public static void main(String[] args)
{
String s1 = new String("abc");
String s2 = s1.intern();
System.out.println(s1 == s2); // return false
}
}