本篇文章為大家展示了如何理解Java 虛擬機(jī)中的String 類和常量池,內(nèi)容簡明扼要并且容易理解,絕對(duì)能使你眼前一亮,通過這篇文章的詳細(xì)介紹希望你能有所收獲。
創(chuàng)新互聯(lián)建站專注于網(wǎng)站建設(shè),為客戶提供網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計(jì)、網(wǎng)頁設(shè)計(jì)開發(fā)服務(wù),多年建網(wǎng)站服務(wù)經(jīng)驗(yàn),各類網(wǎng)站都可以開發(fā),品牌網(wǎng)站設(shè)計(jì),公司官網(wǎng),公司展示網(wǎng)站,網(wǎng)站設(shè)計(jì),建網(wǎng)站費(fèi)用,建網(wǎng)站多少錢,價(jià)格優(yōu)惠,收費(fèi)合理。
一、String 對(duì)象的兩種創(chuàng)建方式
String str1 = "abcd"; String str2 = new String("abcd"); System.out.println(str1==str2); //false
這兩種不同的創(chuàng)建方法是有差別的:
第一種方式是在常量池中獲取對(duì)象(“abcd” 屬于字符串字面量,因此編譯時(shí)期會(huì)在常量池中創(chuàng)建一個(gè)字符串對(duì)象);
第二種方式一共會(huì)創(chuàng)建兩個(gè)字符串對(duì)象(前提是 String Pool 中還沒有 “abcd” 字符串對(duì)象)。
“abcd” 屬于字符串字面量,因此編譯時(shí)期會(huì)在常量池中創(chuàng)建一個(gè)字符串對(duì)象,該字符串對(duì)象指向這個(gè) “abcd” 字符串字面量;
使用 new 的方式會(huì)在堆中創(chuàng)建一個(gè)字符串對(duì)象。
str1 指向常量池中的 “abcd”,而 str2 指向堆中的字符串對(duì)象。
intern() 方法設(shè)計(jì)的初衷,就是重用 String 對(duì)象,以節(jié)省內(nèi)存消耗。
JDK6:當(dāng)調(diào)用intern方法的時(shí)候,如果字符串常量池先前已創(chuàng)建出該字符串對(duì)象,則返回常量池中的該字符串的引用。否則,將此字符串對(duì)象添加到字符串常量池中,并且返回該字符串對(duì)象的引用。
JDK6+:當(dāng)調(diào)用intern方法的時(shí)候,如果字符串常量池先前已創(chuàng)建出該字符串對(duì)象,則返回常量池中的該字符串的引用。否則,如果該字符串對(duì)象已存在與Java堆中,則將堆中對(duì)此對(duì)象的引用添加到字符串常量池中,并且返回該引用;如果堆中不存在,則在常量池中創(chuàng)建該字符串并返回其引用。
在 JVM 運(yùn)行時(shí)數(shù)據(jù)區(qū)中的方法區(qū)有一個(gè)常量池,但是發(fā)現(xiàn)在 JDK 1.6 以后常量池被放置在了堆空間,因此常量池位置的不同影響到了 String 的 intern() 方法的表現(xiàn)。
String s = new String("1"); s.intern(); String s2 = "1"; System.out.println(s == s2); String s3 = new String("1") + new String("1"); s3.intern(); String s4 = "11"; System.out.println(s3 == s4);
JDK 1.6 及以下
上述代碼輸出結(jié)果:
false false
解釋:
在 JDK 1.6 中所有的輸出結(jié)果都是 false,因?yàn)?JDK 1.6 以及以前版本中,常量池是放在 PermGen 區(qū)(屬于方法區(qū))中的,而方法區(qū)和堆區(qū)是完全分開的。
使用引號(hào)聲明的字符串會(huì)直接在字符串常量池中生成的,而 new 出來的 String 對(duì)象是放在堆空間中的。所以兩者的內(nèi)存地址肯定是不相同的,即使調(diào)用了 intern() 方法也是不影響的。
intern() 方法在 JDK 1.6 中的作用:比如 String s = new String(“1”);,再調(diào)用 s.intern(),此時(shí)返回值還是字符串”1”,表面上看起來好像這個(gè)方法沒什么用處。但實(shí)際上,在 JDK1.6 中:檢查字符串常量池里是否存在 “1” 這么一個(gè)字符串,如果存在,就返回池里的字符串;如果不存在,該方法會(huì)把 “1” 添加到字符串常量池中,然后再返回它的引用。
JDK 1.6 及以上
上述代碼輸出結(jié)果:
false true
解釋:String s= new String("1")
生成了字符串常量池中的 “1” 和堆空間中的字符串對(duì)象。
s.intern() s
對(duì)象去字符串常量池中尋找后,發(fā)現(xiàn) “1” 已存在于常量池中。
String s2 = "1"
生成 s2 的引用指向常量池中的 “1” 對(duì)象。
顯然,s 和 s2 的引用地址是不同的。
String s3 = new String("1") + new String("1")
在字符串常量池中生成 “1”,并在堆空間中生成 s3 引用指向的對(duì)象(內(nèi)容為 “11”)。 注意此時(shí)常量池中是沒有 “11” 對(duì)象。
s3.intern()
將 s3 中的 “11” 字符串放入字符串常量池中。 JDK 1.6 的做法是直接在常量池中生成一個(gè) “11” 的對(duì)象。但在 JDK 1.7 中,常量池中不需要再存儲(chǔ)一份對(duì)象了,可以直接存儲(chǔ)堆中的引用。這份引用直接指向 s3 引用的對(duì)象,也就是說 s3.intern() == s3 會(huì)返回 true。
String s4 = "11"
, 這一行代碼會(huì)直接去常量池中創(chuàng)建,但是發(fā)現(xiàn)已經(jīng)有這個(gè)對(duì)象了,此時(shí) s4 就是指向 s3 引用對(duì)象的一個(gè)引用。因此 s3 == s4 返回了true。
String str1 = "str"; String str2 = "ing"; String str3 = "str" + "ing";//常量池中的對(duì)象 String str4 = str1 + str2; //TODO:在堆上創(chuàng)建的新的對(duì)象 String str5 = "string";//常量池中的對(duì)象 System.out.println(str3 == str4);//false System.out.println(str3 == str5);//true System.out.println(str4 == str5);//false
注意:盡量避免多個(gè)字符串拼接,因?yàn)檫@樣會(huì)重新創(chuàng)建對(duì)象。 如果需要改變字符串的話,可以使用 StringBuilder 或者 StringBuffer。
面試題:String s1 = new String(“abc”);問創(chuàng)建了幾個(gè)對(duì)象?
創(chuàng)建2個(gè)字符串對(duì)象(前提是 String Pool 中還沒有 “abcd” 字符串對(duì)象)。
“abc” 屬于字符串字面量,因此編譯時(shí)期會(huì)在常量池中創(chuàng)建一個(gè)字符串對(duì)象,指向這個(gè) “abcd” 字符串字面量;
使用 new 的方式會(huì)在堆中創(chuàng)建一個(gè)字符串對(duì)象。
(字符串常量”abc”在編譯期就已經(jīng)確定放入常量池,而 Java 堆上的”abc”是在運(yùn)行期初始化階段才確定)。
String s1 = new String("abc");// 堆內(nèi)存的地址值 String s2 = "abc"; System.out.println(s1 == s2);// 輸出false //因?yàn)橐粋€(gè)是堆內(nèi)存,一個(gè)是常量池的內(nèi)存,故兩者是不同的。 System.out.println(s1.equals(s2));// 輸出true
上述內(nèi)容就是如何理解Java 虛擬機(jī)中的String 類和常量池,你們學(xué)到知識(shí)或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識(shí)儲(chǔ)備,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
網(wǎng)站名稱:如何理解Java虛擬機(jī)中的String類和常量池
當(dāng)前鏈接:http://www.rwnh.cn/article42/jisehc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供ChatGPT、自適應(yīng)網(wǎng)站、企業(yè)網(wǎng)站制作、網(wǎng)站排名、App開發(fā)、微信公眾號(hào)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)