JVM_04 字符串常量池(详解intern( ))
一、String的基本特性
String:字符串,使用一對""引起來表示。
String sl = “hello”;//字面量的定義方式
String s2 = new String(“hello”)
String聲明為final的,不可被繼承
String實(shí)現(xiàn)了Serializable接口:表示字符串是支持序列化的。 實(shí)現(xiàn)了Comparable接口:表示String可以比較大小
String在jdk8及以前內(nèi)部定義了final char[],value用于存儲(chǔ)字符串?dāng)?shù)據(jù)。jdk9時(shí)改為byte[ ]
String:代表不可變的字符序列。簡稱:不可變性。
通過字面量的方式(區(qū)別于new)給一個(gè)字符串賦值,此時(shí)的字符串值聲明在字符串常量池中
字符串常量池中是不會(huì)存儲(chǔ)相同內(nèi)容的字符串的
- 1.String的String Pool 是一個(gè)固定大小的Hashtable,默認(rèn)值大小長度是1009。如果放進(jìn)StringPool的String非常多,就會(huì)造成Hash沖突嚴(yán)重,從而導(dǎo)致鏈表會(huì)很長,而鏈表長了后直接會(huì)造成的影響就是當(dāng)調(diào)用String. intern時(shí)性能會(huì)大幅下降。
- 2.使用 -XX:StringTableSize可設(shè)置StringTable的長度
- 3.在jdk6中StringTable是固定的,就是1009的長度,所以如果常量池中的字符串過多就會(huì)導(dǎo)致效率下降很快。StringTableSize設(shè) 置沒有要求
- 4.在jdk7中,StringTable的長度默認(rèn)值是60013
- 5.jdk8開始,1009是StringTable長度可設(shè)置的最小值
二、String的內(nèi)存分配
- 1.直接使用雙引號聲明出來的String對象會(huì)直接存儲(chǔ)在常量池中(比如: String info = “abc” )
- 2.如果不是用雙引號聲明的String對象,可以使用String提供的intern()方法
三、字符串拼接操作
常量與常量的拼接結(jié)果在常量池,原理是編譯期優(yōu)化
常量池中不會(huì)存在相同內(nèi)容的常量。
只要其中有一個(gè)是變量,結(jié)果就在堆中
(只有有一個(gè)是變量,那么它會(huì)在堆中創(chuàng)建一個(gè)StringBuilder,調(diào)用append( )方法進(jìn)行添加操作,調(diào)用toString( )方法轉(zhuǎn)換為字符串【toString( )方法其實(shí)就是:new String( )】)
- 1.JDK1.6,將這個(gè)字符串對象嘗試放入串池
①. 如果字符串常量池中有,則并不會(huì)放入。返回已有的串池中的對象的地址
②.如果沒有,它會(huì)在常量池中創(chuàng)建一個(gè)對象放入串池中,并返回串池中的對象地址 - 2.JDK1.7,將這個(gè)字符串對象嘗試放入串池
①. 如果字符串常量池中有,則并不會(huì)放入。返回已有的串池中的對象的地址
②. 如果沒有,它不會(huì)創(chuàng)建一個(gè)對象,如果堆中已經(jīng)這個(gè)字符串,那么會(huì)將堆中的引用地址賦給它 - 3.test3、test4重點(diǎn)掌握
四、拼接操作與append的效率對比
五、intern()的使用 (超級重要)
前言:
- (1). 如果不是用雙引號聲明的String對象,可以使用String提供的intern方法:intern方法會(huì)從字符串常量池中查詢當(dāng)前字符串是否存在,若不存在就會(huì)將當(dāng)前字符串放入常量池中
- (2). 比如: String myInfo = new String(“I love u”).intern(); 也就是說,如果在任意字符串上調(diào)用String. intern方法,那么其返回結(jié)果所指向的那個(gè)類實(shí)例,必須和直接以常量形式出現(xiàn)的字符串實(shí)例完全相同。因此,下 列表達(dá)式的值必定是true:(“a” + “b” + “c”).intern()== “abc”;
- (3). 通俗點(diǎn)講,Interned String就是確保字符串在內(nèi)存里只有一份拷貝,這樣可以節(jié)約內(nèi)存空間,加快字符串操作任務(wù)的執(zhí)行速度。注意,這個(gè)值會(huì)被存放在字符串內(nèi)部池(String
Intern Pool)
①. new String(“ab”)會(huì)創(chuàng)建幾個(gè)對象 很重要
(new String(“ab”)會(huì)創(chuàng)建幾個(gè)對象?看字節(jié)碼,就知道是兩個(gè))
②. new String(“a”) + new String(“b”)呢? 很重要
(在常量池中是沒有ab存在的 [很關(guān)鍵] )
-
對象1:new StringBuilder()
-
對象2: new String(“a”)
-
對象3: 常量池中的"a"
-
對象4: new String(“b”)
-
對象5: 常量池中的"b"
-
深入剖析: StringBuilder的toString(): 對象6 :new String(“ab”)
-
注意:強(qiáng)調(diào)一下,toString()的調(diào)用,在字符串常量池中,沒有生成"ab" 沒有l(wèi)dc指令
四、總結(jié)String的intern()的使用
- JDK1.6,將這個(gè)字符串對象嘗試放入串池
①. 如果字符串常量池中有,則并不會(huì)放入。返回已有的串池中的對象的地址
②.如果沒有,它會(huì)在常量池中創(chuàng)建一個(gè)對象放入串池中,并返回串池中的對象地址 - JDK1.7,將這個(gè)字符串對象嘗試放入串池
①.如果字符串常量池中有,則并不會(huì)放入。返回已有的串池中的對象的地址
②.如果沒有,它不會(huì)創(chuàng)建一個(gè)對象,如果堆中已經(jīng)這個(gè)字符串,那么會(huì)將堆中的引用地址賦給它
intern題目:
六、intern()效率測試
大的網(wǎng)站平臺(tái),需要內(nèi)存中存儲(chǔ)大量的字符串。比如社交網(wǎng)站,很多人都存儲(chǔ):北京市、海淀區(qū)等信息。這時(shí)候如果字符串都調(diào)用 intern()方法,就會(huì)明顯降低內(nèi)存的大小。
/*** 使用intern()測試執(zhí)行效率:空間使用上** 結(jié)論:對于程序中大量存在存在的字符串,尤其其中存在很多重復(fù)字符串時(shí),使用intern()可以節(jié)省內(nèi)存空間。**/ public class StringIntern2 {static final int MAX_COUNT = 1000 * 10000;static final String[] arr = new String[MAX_COUNT];public static void main(String[] args) {Integer[] data = new Integer[]{1,2,3,4,5,6,7,8,9,10};long start = System.currentTimeMillis();for (int i = 0; i < MAX_COUNT; i++) { // arr[i] = new String(String.valueOf(data[i % data.length]));arr[i] = new String(String.valueOf(data[i % data.length])).intern();}long end = System.currentTimeMillis();System.out.println("花費(fèi)的時(shí)間為:" + (end - start));try {Thread.sleep(1000000);} catch (InterruptedException e) {e.printStackTrace();}System.gc();} }七、 StrtingTable的垃圾回收(了解)
/*** String的垃圾回收:* -Xms15m -Xmx15m -XX:+PrintStringTableStatistics -XX:+PrintGCDetails**/ public class StringGCTest {public static void main(String[] args) { // for (int j = 0; j < 100; j++) { // String.valueOf(j).intern(); // }//發(fā)生垃圾回收行為for (int j = 0; j < 100000; j++) {String.valueOf(j).intern();}} }總結(jié)
以上是生活随笔為你收集整理的JVM_04 字符串常量池(详解intern( ))的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 中国剧本推理市场洞察2021
- 下一篇: 2022零售行业消费趋势新主张