String s1 = "ha"; String s2 = "ha"; String s3 = s1 +s2; String s4 = "ha" + "ha"; String s5 = "haha"; String s6 = new String("haha"); System.out.println(s3 == s4); System.out.println(s4 == s5); System.out.println(s5 == s6);
輸出:java
false數組
trueapp
falseui
s3本質調用了 new StringBuilder.append("a").append("b").toString(); 聲明瞭新的引用變量,開闢了新的空間,因此指向的是堆中的對象地址而不是StringTable中的字符串了。spa
s6同理3d
s4 = "ha" + "ha";由於是兩個常量拼接,在編譯時就會直接變成"haha"進行處理,進入StringTablecode
s5 = "haha",由於也是常量,會先在StringTable中查找,找到後s5指向了StringTable中的"haha",所以s4 == s5返回true。對象
String.intern()方法,若是String在StringTable中不存在,則能夠將這個String加入StringTable中,並返回這個對象。blog
好比上面的方法中加入s3.intern(),內存
String s1 = "ha"; String s2 = "ha"; String s3 = s1 +s2; s3.intern(); String s4 = "ha" + "ha"; System.out.println(s3 == s4);
輸出:
true
由於s3的值"haha"被放入了StringTable,s3指向了StringTable的"haha"對象
把haha變爲main
String s1 = "ma"; String s2 = "in"; String s3 = s1 +s2; s3.intern(); String s4 = "ma" + "in"; System.out.println(s3 == s4);
輸出:
main String,java等屬於關鍵詞,在一開始就在StringTable中存在了,因此s3.intern沒能插入進去。
改回haha,若是再在s3前加入一個String ss = "haha";
String s1 = "ha"; String s2 = "ha"; String ss = "haha"; String s3 = s1 +s2; s3.intern(); String s4 = "ha" + "ha"; System.out.println(s3 == s4);
輸出:
false
由於s3.intern()執行時發現StringTable中有了"haha"了,因此沒能加入成功,s3依舊是指向了堆內存中的對象。
-Xms500m 設置堆內存爲500mb
-XX:StringTableSize=2000 將StringTable中的桶個數設爲2000。 hash表桶的數量越多(數組部分長度越長),數據越分散,hashcode撞車的機率越小,速度越快。 默認值是6萬多
-XX:+PrintStringTableStatistics 顯示StringTable的情況。
StringTable有內存回收機制
打開「Run->Edit Configurations」菜單
在VM option(虛擬機設置)中,加入代碼:-XX:StringTableSize=2000 ,點擊ok,而後運行下面的代碼
long t1 = new Date().getTime(); String[] a = new String[1000000]; for(int i=0; i<1000000; i++){ a[i] = ("" + i).intern(); } long t2 = new Date().getTime(); System.out.println(t2 - t1);
運行時間爲9000多毫秒。
而後修改VM option:-XX:StringTableSize=20000,點擊ok,而後再嘗試
運行時間爲1000多毫秒
而後修改VM option:-XX:StringTableSize=200000,點擊ok,而後再嘗試
運行時間爲400多毫秒