java语言特点 字符串不变_面试必问:Java中String类型为什么设计成不可变的?
這幾天在各大平臺(tái)上都看到過(guò)這樣一些帖子,全都是關(guān)于String類型對(duì)象不可變的問(wèn)題,當(dāng)然現(xiàn)在也是找工作的準(zhǔn)備時(shí)期,因此花了一部分時(shí)間對(duì)其進(jìn)行整理一下。
想要完全了解String,在這里我們需要解決以下幾個(gè)問(wèn)題
(1)什么是不可變對(duì)象?
(2)String如何被設(shè)計(jì)成不可變對(duì)象的?
(3)有什么辦法能夠改變String?
(4)JAVA語(yǔ)言為什么把String類型設(shè)計(jì)成不可變?
帶著這些問(wèn)題就可以開(kāi)始今天的文章了。
一、什么是不可變對(duì)象
從字面意思也能夠理解,也就是我們的創(chuàng)建的對(duì)象不可改變。那什么是不可變呢?為了實(shí)現(xiàn)創(chuàng)建的對(duì)象不可變,java語(yǔ)言要求我們需要遵守以下5條規(guī)則:
(1)類內(nèi)部所有的字段都是final修飾的。
(2)類內(nèi)部所有的字段都是私有的,也就是被private修飾。
(3)類不能夠被集成和拓展。
(4)類不能夠?qū)ν馓峁┠男┠軌蛐薷膬?nèi)部狀態(tài)的方法,setter方法也不行。
(5)類內(nèi)部的字段如果是引用,也就是說(shuō)可以指向可變對(duì)象,那我們程序員不能獲取這個(gè)應(yīng)用。
正是由于我們的String類型遵循了上面5條規(guī)則,所以才說(shuō)String對(duì)象是不可變的。想要去了解他還是看看String類型內(nèi)部長(zhǎng)什么樣子再來(lái)看上面5條規(guī)則吧。
二、String如何被設(shè)計(jì)成不可變對(duì)象的
1、疑惑一
在看之前,我們先給出一個(gè)疑惑問(wèn)題,我們看下面的代碼,
在文章一開(kāi)始我們就說(shuō)了,String對(duì)象是不可變的,這里a=張三,然后a=李四,這符合String的不可變性嘛?答案是當(dāng)然符合。
從上面這張圖我們可以看到,在第一次String a="張三"的時(shí)候,在堆中創(chuàng)建了同一個(gè)對(duì)象“張三”。后來(lái)我們?cè)趫?zhí)行a="李四"的時(shí)候再內(nèi)存中又創(chuàng)建了一個(gè)對(duì)象“李四”。也就是說(shuō)我們的a僅僅只是改變了引用a指向的地址而已。
2、源碼解釋疑惑
既然a指向的引用地址改變了,那么其String內(nèi)部肯定有一個(gè)變量,能夠指向不同的實(shí)際對(duì)象,想要進(jìn)一步弄清楚我們就進(jìn)入其String的內(nèi)部來(lái)看看。
我們?cè)谶@里主要通過(guò)String類的源碼來(lái)分析,看一下Java語(yǔ)言是如何設(shè)計(jì),能把String類型設(shè)計(jì)成不可變的。這里給出的是jdk1.8的一部分源碼。
上面最主要的是兩個(gè)字段:value和hash。我們?cè)谶@里主要是看value數(shù)組,hash和主題無(wú)關(guān)所以這里不再講解了,我有專門的文章介紹hash。
我們的String對(duì)象其實(shí)在內(nèi)部就是一個(gè)個(gè)字符然后存儲(chǔ)在這個(gè)value數(shù)組里面的。但是value對(duì)外沒(méi)有setValue的方法,所以整個(gè)String對(duì)象在外部看起來(lái)就是不可變的。我們畫一張圖解釋一下上面的疑惑
現(xiàn)在明白了吧,也就是說(shuō)真正改變引用的是value,因?yàn)関alue也是一個(gè)數(shù)組引用。這也可以很方便的解釋下一個(gè)疑惑問(wèn)題了。
3、疑惑二
既然我們的String是不可變的,好像內(nèi)部還有很多substring, replace, replaceAll這些操作的方法。好像都是對(duì)String對(duì)象改變了,解釋起來(lái)也很簡(jiǎn)單,我們每次的replace這些操作,其實(shí)就是在堆內(nèi)存中創(chuàng)建了一個(gè)新的對(duì)象。然后我們的value指向不同的對(duì)象罷了。
面試的時(shí)候我們只是解釋上面的原因其實(shí)不是那么盡善盡美,想要更好的去加薪去裝逼,我們還需更進(jìn)一步回答。
三、有什么辦法能夠改變String
既然有這個(gè)標(biāo)題。那肯定就是有辦法的,別忘了我們的反射機(jī)制,在通常情況下,他可以做出一些違反語(yǔ)言設(shè)計(jì)原則的事情。這也是一個(gè)技巧,每當(dāng)面試官問(wèn)一些違反語(yǔ)言設(shè)計(jì)原則的問(wèn)題,你就可以拿反射來(lái)反駁他。下面我們來(lái)看一下:
我們可以通過(guò)反射來(lái)改變String。
現(xiàn)在我們知道它的原理以及用法,也知道可以通過(guò)反射來(lái)改變String,還有一個(gè)問(wèn)題我們沒(méi)有弄清楚,面試的時(shí)候你也可以反問(wèn)他,來(lái)進(jìn)一步提升自己的逼格。
四、JAVA語(yǔ)言為什么把String類型設(shè)計(jì)成不可變
這里有幾個(gè)特點(diǎn)。
第一:在Java程序中String類型是使用最多的,這就牽扯到大量的增刪改查,每次增刪改差之前其實(shí)jvm需要檢查一下這個(gè)String對(duì)象的安全性,就是通過(guò)hashcode,當(dāng)設(shè)計(jì)成不可變對(duì)象時(shí)候,就保證了每次增刪改查的hashcode的唯一性,也就可以放心的操作。
第二:網(wǎng)絡(luò)連接地址URL,文件路徑path通常情況下都是以String類型保存, 假若String不是固定不變的,將會(huì)引起各種安全隱患。就好比我們的密碼不能以String的類型保存,,如果你將密碼以明文的形式保存成字符串,那么它將一直留在內(nèi)存中,直到垃圾收集器把它清除。而由于字符串被放在字符串緩沖池中以方便重復(fù)使用,所以它就可能在內(nèi)存中被保留很長(zhǎng)時(shí)間,而這將導(dǎo)致安全隱患
第三:字符串值是被保留在常量池中的,也就是說(shuō)假若字符串對(duì)象允許改變,那么將會(huì)導(dǎo)致各種邏輯錯(cuò)誤
總結(jié)
以上是生活随笔為你收集整理的java语言特点 字符串不变_面试必问:Java中String类型为什么设计成不可变的?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 骁龙8+真的”凉了“?小米12S系列挑战
- 下一篇: java 基本类型 引用类型_Java中