<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          漫話:如何給女朋友解釋為什么Java里面的String對(duì)象是不可變的?

          共 2522字,需瀏覽 6分鐘

           ·

          2021-03-22 13:26

          String的不變性

          String在Java中特別常用,相信很多人都看過(guò)他的源碼,在JDK中,關(guān)于String的類聲明是這樣的:

          public final class String
          implements java.io.Serializable, Comparable&lt;String&gt;, CharSequence {
          }

          可以看到,String類是final類型的,那么也就是說(shuō),String是一個(gè)不可變對(duì)象。

          不可變對(duì)象是在完全創(chuàng)建后其內(nèi)部狀態(tài)保持不變的對(duì)象。這意味著,一旦對(duì)象被賦值給變量,我們既不能更新引用,也不能通過(guò)任何方式改變內(nèi)部狀態(tài)。

          可是有人會(huì)有疑惑,String為什么不可變,我的代碼中經(jīng)常改變String的值啊,如下:

          String s = "abcd";
          s = s.concat("ef");

          這樣,操作,不就將原本的"abcd"的字符串改變成"abcdef"了么?

          但是,雖然字符串內(nèi)容看上去從"abcd"變成了"abcdef",但是實(shí)際上,我們得到的已經(jīng)是一個(gè)新的字符串了。

          如上圖,在堆中重新創(chuàng)建了一個(gè)"abcdef"字符串,和"abcd"并不是同一個(gè)對(duì)象。

          所以,一旦一個(gè)string對(duì)象在內(nèi)存(堆)中被創(chuàng)建出來(lái),他就無(wú)法被修改。而且,String類的所有方法都沒(méi)有改變字符串本身的值,都是返回了一個(gè)新的對(duì)象。

          如果我們想要一個(gè)可秀改的字符串,可以選擇StringBuffer 或者 StringBuilder這兩個(gè)代替String。

          為什么String要設(shè)計(jì)成不可變

          在知道了"String是不可變"的之后,大家是不是一定都很疑惑:為什么要把String設(shè)計(jì)成不可變的呢?有什么好處呢?

          這個(gè)問(wèn)題,困擾過(guò)很多人,甚至有人直接問(wèn)過(guò)Java的創(chuàng)始人James Gosling。

          在一次采訪中James Gosling被問(wèn)到什么時(shí)候應(yīng)該使用不可變變量,他給出的回答是:

          I would use an immutable whenever I can.

          那么,他給出這個(gè)答案背后的原因是什么呢?是基于哪些思考的呢?

          其實(shí),主要是從緩存、安全性、線程安全和性能等角度觸發(fā)的。

          緩存 

          字符串是使用最廣泛的數(shù)據(jù)結(jié)構(gòu)。大量的字符串的創(chuàng)建是非常耗費(fèi)資源的,所以,Java提供了對(duì)字符串的緩存功能,可以大大的節(jié)省堆空間。

          JVM中專門開(kāi)辟了一部分空間來(lái)存儲(chǔ)Java字符串,那就是字符串池。

          通過(guò)字符串池,兩個(gè)內(nèi)容相同的字符串變量,可以從池中指向同一個(gè)字符串對(duì)象,從而節(jié)省了關(guān)鍵的內(nèi)存資源。

          String s = "abcd";
          String s2 = s;

          對(duì)于這個(gè)例子,s和s2都表示"abcd",所以他們會(huì)指向字符串池中的同一個(gè)字符串對(duì)象:

          但是,之所以可以這么做,主要是因?yàn)樽址牟蛔冃浴T囅胍幌?,如果字符串是可變的,我們一旦修改了s的內(nèi)容,那必然導(dǎo)致s2的內(nèi)容也被動(dòng)的改變了,這顯然不是我們想看到的。

          安全性 

          字符串在Java應(yīng)用程序中廣泛用于存儲(chǔ)敏感信息,如用戶名、密碼、連接url、網(wǎng)絡(luò)連接等。JVM類加載器在加載類的時(shí)也廣泛地使用它。

          因此,保護(hù)String類對(duì)于提升整個(gè)應(yīng)用程序的安全性至關(guān)重要。

          當(dāng)我們?cè)诔绦蛑袀鬟f一個(gè)字符串的時(shí)候,如果這個(gè)字符串的內(nèi)容是不可變的,那么我們就可以相信這個(gè)字符串中的內(nèi)容。

          但是,如果是可變的,那么這個(gè)字符串內(nèi)容就可能隨時(shí)都被修改。那么這個(gè)字符串內(nèi)容就完全可信了。這樣整個(gè)系統(tǒng)就沒(méi)有安全性可言了。

          線程安全

          不可變會(huì)自動(dòng)使字符串成為線程安全的,因?yàn)楫?dāng)從多個(gè)線程訪問(wèn)它們時(shí),它們不會(huì)被更改。

          因此,一般來(lái)說(shuō),不可變對(duì)象可以在同時(shí)運(yùn)行的多個(gè)線程之間共享。它們也是線程安全的,因?yàn)槿绻€程更改了值,那么將在字符串池中創(chuàng)建一個(gè)新的字符串,而不是修改相同的值。因此,字符串對(duì)于多線程來(lái)說(shuō)是安全的。

          hashcode緩存

          由于字符串對(duì)象被廣泛地用作數(shù)據(jù)結(jié)構(gòu),它們也被廣泛地用于哈希實(shí)現(xiàn),如HashMap、HashTable、HashSet等。在對(duì)這些散列實(shí)現(xiàn)進(jìn)行操作時(shí),經(jīng)常調(diào)用hashCode()方法。

          不可變性保證了字符串的值不會(huì)改變。因此,hashCode()方法在String類中被重寫,以方便緩存,這樣在第一次hashCode()調(diào)用期間計(jì)算和緩存散列,并從那時(shí)起返回相同的值。

          在String類中,有以下代碼:

          private int hash;//this is used to cache hash code.

          性能

          前面提到了的字符串池、hashcode緩存等,都是提升性能的提現(xiàn)。

          因?yàn)樽址豢勺?,所以可以用字符串池緩存,可以大大?jié)省堆內(nèi)存。而且還可以提前對(duì)hashcode進(jìn)行緩存,更加高效

          由于字符串是應(yīng)用最廣泛的數(shù)據(jù)結(jié)構(gòu),提高字符串的性能對(duì)提高整個(gè)應(yīng)用程序的總體性能有相當(dāng)大的影響。

          總結(jié)

          通過(guò)本文,我們可以得出這樣的結(jié)論:字符串是不可變的,因此它們的引用可以被視為普通變量,可以在方法之間和線程之間傳遞它們,而不必?fù)?dān)心它所指向的實(shí)際字符串對(duì)象是否會(huì)改變。

          我們還了解了促使Java語(yǔ)言設(shè)計(jì)人員將該類設(shè)置為不可變類的其他原因。主要考慮的是緩存、安全性、線程安全和性能等方面

          關(guān)于作者漫話編程,是一個(gè)通過(guò)漫畫+音頻的形式講解枯燥的編程知識(shí)的公眾號(hào)。致力于讓編程變得更有樂(lè)趣。


          推薦閱讀:


          喜歡我可以給我設(shè)為星標(biāo)哦

          好文章,我“在看”
          瀏覽 28
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  成人性别视频影音先锋电影 | 91爱电影| 国产一卡二卡在线 | 青青草亚洲视频 | 伊人成人在线视频 |