新聞中心
這篇文章主要介紹“Java字符串的不可變是什么意思”,在日常操作中,相信很多人在Java字符串的不可變是什么意思問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”Java字符串的不可變是什么意思”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!
為甘肅等地區(qū)用戶提供了全套網(wǎng)頁(yè)設(shè)計(jì)制作服務(wù),及甘肅網(wǎng)站建設(shè)行業(yè)解決方案。主營(yíng)業(yè)務(wù)為網(wǎng)站設(shè)計(jì)制作、做網(wǎng)站、甘肅網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠(chéng)的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會(huì)得到認(rèn)可,從而選擇與我們長(zhǎng)期合作。這樣,我們也可以走得更遠(yuǎn)!
前言
在 Java 開發(fā)中 String (字符串)對(duì)象是我們使用最頻繁的對(duì)象,也是很重要的對(duì)象。正是使用得如此頻繁,String 在實(shí)現(xiàn)層面上不斷進(jìn)行優(yōu)化,從 Java6 到 Java7,再到 Java9 的新實(shí)現(xiàn) ,都是為了提升 String 對(duì)象的性能,而其中不變的是 String 所生俱來(lái)的特性:不可變。本文主要聊一聊 String 的不可變,以及為什么存在的。
什么是 String 的不可變
首先我們先來(lái)看下什么是不可變對(duì)象:一旦對(duì)象被創(chuàng)建并初始化后,內(nèi)部的狀態(tài)數(shù)據(jù)就會(huì)保持不變。查看 JDK 源碼中的 String 類,可以看到類本身被 final 修飾,并且內(nèi)部的大部分屬性都是 final 修飾的,除了字段 hash 是通過(guò)字符串內(nèi)容計(jì)算并緩存起來(lái)的。這樣的行為讓 String 類無(wú)法被擴(kuò)展,內(nèi)部屬性也無(wú)法被修改。
接著我們?cè)賮?lái)用畫圖的形式來(lái)說(shuō)明下 String 的不可變性。
通常我們初始化字符串都是以下形式:
String 類型的引用變量 a
保留了一個(gè)字符串對(duì)象 string
的引用,就如同下圖所示,箭頭則表示了變量 a
與真正 String 對(duì)象的引用關(guān)系。
再通過(guò)上述代碼,我們將變量 a
賦值給變量 b
,變量 b
也存儲(chǔ)了字符串對(duì)象 string
的引用,它們指向的是同一個(gè)對(duì)象。
當(dāng)我們嘗試對(duì)變量 a
重新賦值,看下對(duì)變量 b
會(huì)不會(huì)有影響呢
想必小伙伴一看就知道,打印的結(jié)果肯定是 string2,string
,同樣用畫圖的方式展示這兩個(gè)變量與字符串對(duì)象的引用關(guān)系。
將變量 a
重新賦值后,保存了新的引用,而不是直接在原有的字符串對(duì)象上進(jìn)行數(shù)據(jù)改變,同時(shí)變量 b
仍然存的是對(duì)象 string
的引用,變量 a
和 b
兩者相互獨(dú)立,不影響,這也正是說(shuō)明了 String 對(duì)象的不可變。
在這里初認(rèn) Java 的小伙伴還可能會(huì)有些困惑:對(duì)一個(gè)String對(duì)象 a
賦值 string
,然后又讓 a
值為 string2
,這個(gè)時(shí)候a的值變成 了string2
, a
的值改變了,為什么還說(shuō) String 對(duì)象不可變呢。
其實(shí)問(wèn)題也很簡(jiǎn)單,這里的 a
只是存儲(chǔ) String 對(duì)象的引用,并不是對(duì)象本身,a
存儲(chǔ)的是指向?qū)ο笏趦?nèi)存的地址引用罷了,當(dāng)?shù)诙钨x值時(shí),a
引用指向了對(duì)象 string2
的內(nèi)存地址,而對(duì)象 string2
是重新創(chuàng)建的,之前的 string
對(duì)象仍在內(nèi)存中,并且由變量 b
引用著。
除此之外,String 類的返回 String 對(duì)象的方法不會(huì)改變自身,都是返回一個(gè)新的 String 對(duì)象來(lái)實(shí)現(xiàn),比如 concat
,replace
,substring
等等。
為什么 String 需要不可變
聊完什么是 String 的不可變后,接下來(lái)我們?cè)僬f(shuō)說(shuō) String 為什么需要不可變呢,又有什么好處呢?
字符串常量池的實(shí)現(xiàn)
在Java中,我們通常有兩種方式創(chuàng)建字符串對(duì)象,一種是通過(guò)字符串字面量方式創(chuàng)建,就如上文的代碼,另外一種就是通過(guò) new 方式去創(chuàng)建,如 String c = new String("string 3");
而兩者區(qū)別就在于通過(guò)字符串字面量的方式創(chuàng)建時(shí),JVM 會(huì)現(xiàn)在字符串池中檢查字符串內(nèi)容是否已經(jīng)存在,如果存在就會(huì)直接返回對(duì)應(yīng)的引用,而不是再次分配內(nèi)存進(jìn)行創(chuàng)建,如果不存在就會(huì)分配在內(nèi)存中創(chuàng)建的同時(shí)將字符串?dāng)?shù)據(jù)緩存在字符串池中,便于重用。正是是由于字符串的不可變,同樣的字符串內(nèi)容可以讓 JVM 可以減少額外的內(nèi)存分配操作,直接使用在字符串池中字符串對(duì)象即可,對(duì)性能提升和內(nèi)存節(jié)省都大有好處。
關(guān)于字符串池,這里稍微簡(jiǎn)單介紹一下:**Java 的字符串池屬于 JVM 專門給指定的特殊內(nèi)存區(qū)域,用來(lái)存儲(chǔ)字符串字面量。**在 Java 7 之前,分配于 JVM 的方法區(qū)內(nèi),屬于常量池的一部分;而 Java7 之后字符串池被移至堆內(nèi)存進(jìn)行管理,這樣的好處就是允許被 JVM 進(jìn)行垃圾回收操作,將未被引用的字符串所占內(nèi)存即使回收,以此節(jié)省內(nèi)存。
Hashcode 緩存
字符串作為基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu),大量地應(yīng)用在一些集合容器之中,尤其是一些散列集合,在散列集合中,存放元素都要根據(jù)對(duì)象的 hashCode()
方法來(lái)確定元素的位置。由于字符串 hashcode
屬性不會(huì)變更,保證了唯一性,使得類似 HashMap,HashSet 等容器才能實(shí)現(xiàn)相應(yīng)的緩存功能。由于 String 的不可變,避免重復(fù)計(jì)算 hashcode
,只有使用緩存的 hashcode
即可,這樣一來(lái)大大提高了在散列集合中使用 String 對(duì)象的性能。
線程安全
在多線程中,只有不變的對(duì)象和值是線程安全的,可以在多個(gè)線程中共享數(shù)據(jù)。由于 String 天然的不可變,當(dāng)一個(gè)線程”修改“了字符串的值,只會(huì)產(chǎn)生一個(gè)新的字符串對(duì)象,不會(huì)對(duì)其他線程的訪問(wèn)產(chǎn)生副作用,訪問(wèn)的都是同樣的字符串?dāng)?shù)據(jù),不需要任何同步操作。
安全性
由于字符串無(wú)論在任何 Java 系統(tǒng)中都廣泛使用,會(huì)用來(lái)存儲(chǔ)敏感信息,如賬號(hào),密碼,網(wǎng)絡(luò)路徑,文件處理等場(chǎng)景里,保證字符串 String 類的安全性就尤為重要了,如果字符串是可變的,容易被篡改,那我們就無(wú)法保證使用字符串進(jìn)行操作時(shí),它是安全的,很有可能出現(xiàn) SQL 注入,訪問(wèn)危險(xiǎn)文件等操作。
結(jié)語(yǔ)
通過(guò)本文,我們介紹 String 是不可變的,可以將它們的引用可以被當(dāng)作一個(gè)普通的變量來(lái)使用,無(wú)論是在方法間,還是線程間傳遞它們,都不用擔(dān)心它指向的實(shí)際 String 對(duì)象發(fā)生改變,并且不可變的特性也在語(yǔ)言層面和程序?qū)用嫔蠋Я嗽S多好處,在平常編程實(shí)踐中我們也應(yīng)該多學(xué)習(xí)效仿,用 James Gosling,Java之父的話說(shuō)就是”我會(huì)盡可能地使用不可變對(duì)象“。
到此,關(guān)于“Java字符串的不可變是什么意思”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!
名稱欄目:Java字符串的不可變是什么意思
分享鏈接:http://fisionsoft.com.cn/article/jdcpsc.html