標籤:style blog color 使用 java ar strong 資料 div
public class StringDemo01 { public static void main(String[] args) { String s1 = new String("abc"); // a String s2 = "abc"; // b String s3 = new String("abc"); // c System.out.println(s1 == s2); //false System.out.println(s1 == s3); //false System.out.println(s2 == s3); //false System.out.println(s1 == s1.intern()); //false System.out.println(s2 == s2.intern()); //true System.out.println(s1.intern() == s2.intern()); //true String lo = "lo"; String hel = "hel"; System.out.println("hello" == "hel" + "lo"); // d //true System.out.println("hello" == "hel" + lo); // e //false System.out.println("hello" == hel + "lo"); // f //false }}1、產生幾個對象
問題:當執行完程式的第a、b、c行之後分別產生幾個對象,分別是什嗎?原因?
1)執行完a後,產生2個對象:
首先先到String Pool中尋找是否有名稱為"abc"的字串,沒有的話在String Pool中新產生一個"abc"對象1,而new String("abc")操作又會在Java記憶體的堆中產生一個"abc"String類對象2,
變數s1是一個引用,存放在棧中並指向堆中的"abc"String對象;
2) 執行完b後,產生0個對象:
String s2= "abc"; 此句程式在執行過程中也會先到String Pool中尋找名稱為"abc"的字串對象,因為在String s1 = new String("abc");時已經在String Pool中產生了"abc"對象,故執行完
這句之後同樣存在於棧的s2對象指向String Pool中的"abc"String對象,即s2中存放"abc"String對象在String Pool中的地址;
3) 執行完c後,產生1個對象:
同樣的道理,首先會到String Pool中尋找是否有"abc"String對象,發現已經存在,然後又通過new的方式在中產生一個新的"abc"String對象,並將其地址賦給引用變數s3;
在此樣本中三個引用變數s1、s2、s3分別指向三個不同的對象,存放著三個不同的記憶體位址,故三者當中任意者用"=="來比較都是false。
s1--------堆中的一個對象,此對象是String Pool中對象的一個拷貝;
s2--------String Pool常量池中的"abc"String對象;
s3--------堆中的一個對象,此對象也是String Pool中對象的一個拷貝;
==判斷小結:
1)對於原生資料類型來說"=="比較的是資料的數值;
2)對於引用資料類型來說"=="比較的永遠是對象的記憶體位址 。
2、intern
查看JDK文檔可知如果有兩個String類型s和t,若且唯若s.equals(t)時,s.intern()==t.intern(),即如果s和t的內容相等時s.intern()和t.intern()都是返回String Pool中同一個對象的引用,
既然是同一個對象的引用地址肯定一樣。 分析s.intern()可知,首先到String Pool常量池中尋找是否有"abc"字串,如果有那麼s.intern()的傳回值就是常量池中"abc"的地址,如果沒有,那麼會先添加到string pool中去,然後將地址返回。
所以可以得到如下關係:s.intern()=s1.intern()=s2.intern()=s1
s1指向的是堆,而s1.intern()指向的是常量池中;
s2指向的是常量池,s2.intern()指向的也是常量池;
s1. intern()指向的是常量池,s2.intern()指向的也是常量池;
3、字串拼接
對於第d行"+"兩端是兩個字面值即常量,故會拼接成一個"hello",然後在String Pool常量池中可以找到,不產生新的對象,等號兩端的地址都是String Pool中" hello"的地址,所以相等,返回true。
對於第e,f行"+"兩端其中一個是字面值即常量而另一個則是變數,無法進行拼接,故會在堆中產生一個"abc"的對象,堆中一個對象和String Pool常量池中一個對象當然是兩個對象,地址值肯定不相
等,所以返回false。
常量池:JVM中一塊獨立的地區存放字串常量和基本類型常量(public static final)
4、在Java中一個字串能否表示一個漢字?
在Java中一個字元表示16位,相當於兩個位元組(1 byte = 8 bit),而一個漢字佔用兩個位元組。
5、String s = "Hello"; s = s + " world!";這兩行代碼執行後,原始的String對象中的內容到底變了沒有?
String對象的內容是不能改變的,最後雖然指向了helloworld,但是原始的String對象的內容還是hello並沒有改變,只是現在不指向它罷了。
6、String s = new String("xyz");建立了幾個String Object? 二者之間有什麼區別?
建立了2個對象,一個在string pool中一個在堆中
7、String 和StringBuffer的區別
String是final類型,內容不可改變的,StringBuffer的內容是可以改變的;
String重寫了equals和hashCode方法,而StringBuffer則沒有。
8、StringBuffer和StringBuilder的區別
StringBuffer是安全執行緒的;
StringBuilder是非安全執行緒的效能高點,推薦使StringBuilder,JDK5以後出現。
9、下面這條語句一共建立了多少個對象:String s="a"+"b"+"c"+"d"
一個。JVM在編譯時間會最佳化,相當於直接定義了一個”abcd”的字串;
String s = "a"+"b"+"c";會產生幾個對象?
只會產生一個對象,編譯期就能確定儲存到常量池中。
使用包含變數的字串串連符如"aa" + s1建立的對象是運行期才建立的,儲存在堆中;
10、String練習
String str1 = "a";String str2 = "b";String str3 = "ab";String str4 = str1 + str2;String str5 = new String("ab");System.out.println(str5.equals(str3)); //trueSystem.out.println(str5 == str3); //falseSystem.out.println(str5.intern() == str3); //trueSystem.out.println(str5.intern() == str4); //falseString a = new String("ab");String b = new String("ab");String c = "ab";String d = "a" + "b";String e = "b";String f = "a" + e;System.out.println(b.intern() == a); //falseSystem.out.println(b.intern() == c); //trueSystem.out.println(b.intern() == d); //trueSystem.out.println(b.intern() == f); //falseSystem.out.println(b.intern() == a.intern()); //trueString a = "abc";String b = "abc";String c = "a" + "b" + "c";String d = "a" + "bc";String e = "ab" + "c";System.out.println(a == b); //trueSystem.out.println(a == c); //trueSystem.out.println(a == d); //trueSystem.out.println(a == e); //trueSystem.out.println(c == d); //trueSystem.out.println(c == e); //true
jdk分析之String