答:1.為了實(shí)現(xiàn)字符串池
? ? ? ? 2.為了線程安全
? ? ? ? 3.為了實(shí)現(xiàn)String可以創(chuàng)建HashCode不可變性
? ? 首先你要理解final的用途定欧,在分析String為什么要用final修飾辈双,final可以修飾類(lèi),方法和變量馏段,并且被修飾的類(lèi)或方法轩拨,被final修飾的類(lèi)不能被繼承,即它不能擁有自己的子類(lèi)院喜,被final修飾的方法不能被重寫(xiě)亡蓉, final修飾的變量,無(wú)論是類(lèi)屬性喷舀、對(duì)象屬性砍濒、形參還是局部變量,都需要進(jìn)行初始化操作硫麻。
在了解final的用途后爸邢,在看String為什么要被final修飾:主要是為了”安全性“和”效率“的緣故。
查看JDK String的源碼
final修飾的String拿愧,代表了String的不可繼承性杠河,final修飾的char[]代表了被存儲(chǔ)的數(shù)據(jù)不可更改性。但是:雖然final代表了不可變,但僅僅是引用地址不可變券敌,并不代表了數(shù)組本身不會(huì)變,請(qǐng)看下面圖片唾戚。
? ? final也可以將數(shù)組本身改變的,這個(gè)時(shí)候陪白,起作用的還有private颈走,正是因?yàn)閮烧弑WC了String的不可變性。
? ? 那么為什么保證String不可變呢,因?yàn)?b>只有當(dāng)字符串是不可變的咱士,字符串池才有可能實(shí)現(xiàn)立由。字符串池的實(shí)現(xiàn)可以在運(yùn)行時(shí)節(jié)約很多heap空間,因?yàn)椴煌淖址兞慷贾赶虺刂械耐粋€(gè)字符串序厉。但如果字符串是可變的锐膜,那么String interning將不能實(shí)現(xiàn),因?yàn)檫@樣的話弛房,如果變量改變了它的值道盏,那么其它指向這個(gè)值的變量的值也會(huì)一起改變。
? ? 如果字符串是可變的文捶,那么會(huì)引起很?chē)?yán)重的安全問(wèn)題荷逞。譬如,數(shù)據(jù)庫(kù)的用戶名粹排、密碼都是以字符串的形式傳入來(lái)獲得數(shù)據(jù)庫(kù)的連接种远,或者在socket編程中,主機(jī)名和端口都是以字符串的形式傳入顽耳。因?yàn)樽址遣豢勺兊淖狗螅运闹凳遣豢筛淖兊模駝t黑客們可以鉆到空子射富,改變字符串指向的對(duì)象的值膝迎,造成安全漏洞。
? ? 因?yàn)樽址遣豢勺兊囊群模?b>是多線程安全的限次,同一個(gè)字符串實(shí)例可以被多個(gè)線程共享。這樣便不用因?yàn)榫€程安全問(wèn)題而使用同步柴灯。字符串自己便是線程安全的卖漫。
? ? 因?yàn)樽址遣豢勺兊模栽谒鼊?chuàng)建的時(shí)候HashCode就被緩存了弛槐,不需要重新計(jì)算。這就使得字符串很適合作為Map中的鍵依啰,字符串的處理速度要快過(guò)其它的鍵對(duì)象乎串。這就是HashMap中的鍵往往都使用字符串。