string的一些操作

針對jdk1.7及1.7+之后的場景:

場景1?

String s ="a" +"b";

String s1 ="ab";

System.out.println(s==s1);

結(jié)果為true,"a" +"b"編譯后直接優(yōu)化為字符串的"ab"。運行的時候“ab”會在字符串常量池中創(chuàng)建一個"ab"然后地址返回給s,s1="ab",會從字符串常量查找"ab"的常量,查到后將引用地址返回給s1。s和s1指向的是字符串常量池中同一個地址,所以為true.

結(jié)論:

1 "ab"會在字符串常量池中生成一個"ab"對象。字符串常量池中數(shù)據(jù)不會重復(fù)。

2?通過編譯后的文件可以看到,"a" +"b"只會在常量池中生成一個對象"ab"。直接經(jīng)過編譯后就只有"ab",看不出"a","b"的信息

場景2

String s = new String("ab")創(chuàng)建幾個對象。


字節(jié)碼文件

通過查看編譯后的字節(jié)碼文件,可以看到有2個對象

1 在堆中new 的一個String對象

2 在字符串常量池中創(chuàng)建一個"ab"的對象

注意:這個時候s引用指向的是堆中的String對象,而不是字符串常量池stringtable中的對象。

所以有:

String s =new String("ab");

String s1 ="ab";

System.out.println(s==s1);

結(jié)果為false,s指向的是堆中創(chuàng)建的對象,s1指向的是字符串常量池中的對象。

場景3:

String s =new String("a") +new String("b");

String s1 ="ab";

System.out.println(s==s1);

這里涉及2個問題:

1?new String("a") +new String("b")創(chuàng)建幾個對象

jdk1.7之后優(yōu)化字符串的+操作會使用stringBuilder的append()操作。

創(chuàng)建的對象(總共6個):

①new StringBuilder()對象

②堆中一個new String("a")對象

③字符串常量池中一個a對象

④堆中一個new String("b")對象

⑤字符串常量池中一個b對象

StringBuilder()調(diào)用toString()在堆中生成的一個對象。

2?s==s1結(jié)果為false。一個是堆中對象,一個是字符串常量池中的對象。

場景4?

String s1 ="a";

String s2 ="b";

String s3 = s1+s2;

String s4 ="ab";

System.out.println(s3==s4);

結(jié)果為false,字符串的+號操作,使用StringBuilder的append方法進行處理。

場景5

final String s1 ="a";

final String s2 ="b";

String s3 = s1+s2;

String s4 ="ab";

System.out.println(s3==s4);

結(jié)果為true,使用final修飾的變量就是一個常量,編譯器在編譯階段可以直接確定s3的值。不會使用StringBuilder進行處理。s3直接指向常量池中"ab",所以s3==s4。

場景6

final String s1 ="a";

String s3 = s1+"b";

String s4 ="ab";

System.out.println(s3==s4);

結(jié)果為true,編譯器優(yōu)化s3直接為"ab"

場景7

final String s1 =new String("a");

String s3 = s1+"b";

String s4 ="ab";

System.out.println(s3==s4); //false

結(jié)果為false,此時的"a"有2個對象。一個是堆中通過 new String()生成的對象,一個是字符串常量池中的對象。s1指向的是堆中new的對象,而堆中new的對象是在運行期才能確定的,所以這個時候雖然s1是一個final修飾的常量,但是編譯器還是會當(dāng)做一個不確定的量使用(new的對象在運行時才能確定),所以當(dāng)編譯器遇到+操作會使用StringBuilder進行處理。結(jié)果為false。

場景8

final String s1 =new String("a");

String s3 = s1+"b";

s3.intern();

String s4 ="ab";

System.out.println(s3==s4);? //true

重要:

結(jié)果為true,String s3 = s1+"b";這個操作會變成stringBuilder的toString()操作,返回的是堆中的對象"ab",這個時候字符串常量池中并沒有"ab"。調(diào)用s3.intern()后,會在常量池中創(chuàng)建一個"ab"的字符串常量,但是此時其實堆中是先有了一個調(diào)用toString()方法new出來的對象,jvm會復(fù)用這個對象,將常量池中的"ab"這個對象直接執(zhí)行堆中new的對象,這個時候再去String s4 ="ab",會指向同一個地址。所以結(jié)果為true。

場景9?

String s1 =new String("a");

s1.intern();

String s2 ="a";

System.out.println(s1==s2);? //false

結(jié)果為false。a在堆中2個對象,一個是字符串常量池中,一個在new的對象中。這個時候s1指向的是堆中new的對象。調(diào)用s1.intern();這個方法會判斷字符串常量池中是否有s1這個對象,如果存在就結(jié)果返回。沒有就創(chuàng)建一個。所以這個時候調(diào)用s1.intern()。其實是無效的。s1指向的是堆中new的地址,s2指向的是常量池中的地址。所以結(jié)果為false。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容