Java字符串常量池示例詳解
為什么會(huì)有常量池的概念?
不知道小伙伴們是否有思考過這個(gè)問題? 沒有思考也無所謂,小編在這里類比一下,大家就會(huì)清晰了。什么是池? 我們聽的最多的池,應(yīng)該是數(shù)據(jù)庫連接池. 為什么會(huì)有數(shù)據(jù)庫連接池,其實(shí)就是為了節(jié)省資源,提高性能,防止重復(fù)創(chuàng)建連接,避免占用內(nèi)存和網(wǎng)絡(luò)資源。
常量池其實(shí)就是跟數(shù)據(jù)庫連接池的目的都是一樣的。那么他是如何實(shí)現(xiàn)的呢? 因?yàn)槌A砍厥荍VM的概念,源碼我們也不好看,所以我們還以連接池來類比。
池化的目標(biāo)就是緩存和管理
稍微提一點(diǎn)池化的概念,其實(shí)就是對(duì)資源做一個(gè)包裝,在包裝層來加一些對(duì)這個(gè)資源的屬性信息,比如使用次數(shù),最后操作時(shí)間,最長生命周期一樣。然后通過后臺(tái)線程對(duì)資源包裝層的掃描,來對(duì)真實(shí)資源的做一個(gè)管理。Google的Guava的Cache就是這么做的,我們自己也可以利用 common-pool2 工具包自己來做,或者說池化。
Java字符串常量池
在 JDK 1.7 之前,HotSpot 虛擬機(jī)中的字符串常量池都在方法區(qū)中,用永生代實(shí)現(xiàn)。JDK 1.7 及以后的版本,字符串常量池移到了堆里。
JDK 1.6 的 String.intern 方法會(huì)將首次遇到的 String 對(duì)象復(fù)制到永久代,并返回這個(gè)對(duì)象的引用。
JDK 1.7 的 String.intern 方法不再復(fù)制,而是記錄首次出現(xiàn)的 String 對(duì)象的引用。
以下用 JDK 1.8 實(shí)驗(yàn)探究字符串常量池。
// test1 String s1 = "red"; String s2 = "red"; System.out.println(s1 == s2); // true // test2 String s3 = new String("red"); String s4 = new String("red"); System.out.println(s3 == s4); // false // test3 System.out.println(s1 == s3); // false // test4 System.out.println(s3.intern() == s1); // true System.out.println(s3.intern() == s3); // false System.out.println(s3.intern() == s4); // false // test5 String s5 = new String("thunder"); String s6 = s5.intern(); String s7 = "thunder"; System.out.println(s5 == s6); // false System.out.println(s6 == s7); // true // test6 String s8 = new String("1") + new String("1"); // String s8 = new StringBuilder().append().toString() String s9 = s8.intern(); String s10 = "11"; System.out.println(s8 == s9); // true System.out.println(s9 == s10); // true
常量池可以看作是一個(gè)集合,沒有重復(fù)的元素。用雙引號(hào)創(chuàng)建的對(duì)象直接放到常量池,new 一定會(huì)在堆中創(chuàng)建一個(gè)新的對(duì)象,如果常量池沒有值相同的對(duì)象那么會(huì)在常量池也創(chuàng)建一個(gè)對(duì)象。intern 的作用是判斷常量池是否包含值相同的字符串,是則返回這個(gè)字符串對(duì)象的引用,否則將當(dāng)前實(shí)例的引用放到常量池并返回當(dāng)前實(shí)例的引用。
另外,字符串的拼接實(shí)際上是用了 StringBuilder,所以字符串 s8 的創(chuàng)建會(huì)伴隨以下對(duì)象的創(chuàng)建:
- 堆中兩個(gè)不同的 String 對(duì)象 1
- 字符串常量池中一個(gè) String 對(duì)象 1
- 一個(gè) StringBuilder 對(duì)象
- 堆中的 String 對(duì)象 11
由于 s8 的創(chuàng)建方式不是 new String 而是拼接,所以不會(huì)在常量池中創(chuàng)建值為“11”的對(duì)象,這也是 test5 和 test6 要對(duì)比的問題。
總結(jié)
到此這篇關(guān)于Java字符串常量池的文章就介紹到這了,更多相關(guān)Java字符串常量池內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java封裝數(shù)組之動(dòng)態(tài)數(shù)組實(shí)現(xiàn)方法詳解
這篇文章主要介紹了Java封裝數(shù)組之動(dòng)態(tài)數(shù)組實(shí)現(xiàn)方法,結(jié)合實(shí)例形式詳細(xì)分析了java動(dòng)態(tài)數(shù)組的實(shí)現(xiàn)原理、操作步驟與相關(guān)注意事項(xiàng),需要的朋友可以參考下2020-03-03SpringBoot Swagger2 接口規(guī)范示例詳解
Swagger(在谷歌、IBM、微軟等公司的支持下)做了一個(gè)公共的文檔風(fēng)格來填補(bǔ)上述問題,在本文中,我們將會(huì)學(xué)習(xí)怎么使用Swagger的 Swagger2注解去生成REST API文檔,感興趣的朋友一起看看吧2023-12-12Java C++題解leetcode816模糊坐標(biāo)示例
這篇文章主要為大家介紹了Java C++題解leetcode816模糊坐標(biāo)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01Java8新的異步編程方式CompletableFuture實(shí)現(xiàn)
這篇文章主要介紹了Java8新的異步編程方式CompletableFuture實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-04-04springboot熱部署知識(shí)點(diǎn)總結(jié)
在本篇文章里小編給大家整理了關(guān)于springboot熱部署的知識(shí)點(diǎn)內(nèi)容,有興趣的朋友們參考學(xué)習(xí)下。2019-06-06解決BigDecimal轉(zhuǎn)long丟失精度的問題
這篇文章主要介紹了解決BigDecimal轉(zhuǎn)long丟失精度的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-12-12