分析Java中為什么String不可變
常量池
Java中我們創(chuàng)建String對(duì)象有兩種基本方法。
String str1 = "zxhtom"; String str2 = new String("zxhtom");
上面兩種方式我們創(chuàng)建了兩個(gè)String變量 。 但是第一種通過雙引號(hào)創(chuàng)建的zxhtom這個(gè)對(duì)象我們稱之為常量 。 在JVM中是存儲(chǔ)在一塊叫【常量池】中的。而第二種str2是我們稱之為普通變量。new一次就在JVM中開辟一塊內(nèi)存。
【常量池】的作用就是復(fù)用,當(dāng)同樣的內(nèi)容再次被通過常量方式創(chuàng)建的時(shí)候Java會(huì)指向同一塊地址。通過如下代碼理解:
String z1 = "zxhtom"; String z2 = "zxhtom";
通過上圖我們可以了解 z1 , z2兩個(gè)變量其實(shí)引用的是同一內(nèi)存地址 。 所以z1==z2 為true .
到這里引發(fā)出為什么String被設(shè)計(jì)為不可變 。 上列中z1 被修改成zxh . 如果String是可變得那么z2就會(huì)被莫名其妙修改成zxh .
便利
在Java中判斷兩個(gè)對(duì)象相等時(shí)通過地址判斷。但是地址被抽象話為一段hash函數(shù)。在Java使用中hash是經(jīng)常被使用的。將String設(shè)置為不可變性那么hash就可以一直使用下去。不需要重新計(jì)算體現(xiàn)了便捷性
安全
仍是上面的情況 , z2會(huì)被不知情的情況下被修改了。這在多線程中很常見。我們?cè)谑褂玫臅r(shí)候會(huì)被其他情況將數(shù)據(jù)更改。這樣我們的數(shù)據(jù)將會(huì)失去了準(zhǔn)確性。
引申問題
在上部中我們提到String的常量池。針對(duì)常量池引發(fā)思考 【String.intern()】
該方法的功能就是擴(kuò)充【常量池】。z2.intern() 表示判斷常量池中是否存在與該值相同的對(duì)象如果有則返回該對(duì)象的引用。 如果沒有則將該值注冊(cè)到內(nèi)存中。注意這里并不是將z2對(duì)象注冊(cè)過去。而是將z2的值注冊(cè)進(jìn)去。
String z1=new String("zxhtom"); String z2=z1.intern(); System.out.println( z1==z1.intern() ); System.out.println( z1.hashCode()+" "+z2.hashCode() ); System.out.println( z2==z1 ); System.out.println( z2==z1.intern() );
輸出結(jié)構(gòu)
false
-688175064 -688175064
false
true
分析一下輸出結(jié)果不難發(fā)現(xiàn),z1.intern()是常量池中沒有zxhtom,會(huì)將zxhtom值創(chuàng)建到常量池中,z2就是引用常量池中的引用。這個(gè)時(shí)候z1==z2 為false說明注冊(cè)到常量池中的并不是z1的地址,而是相當(dāng)于z1的一個(gè)對(duì)象拷貝。
string創(chuàng)建方式的確定簡(jiǎn)單歸結(jié):
- 通過雙引號(hào)創(chuàng)建的 == 常量創(chuàng)建
- 通過常量拼接 == 常量創(chuàng)建
- 通過非常量與常量拼接 = 非常量創(chuàng)建
- 通過new 創(chuàng)建 == 非常量創(chuàng)建
String在Java中的【引用傳遞】
在Java中方法參數(shù)傳遞都是通過值傳遞的。但是為什么String給我們的感覺是引用傳遞的呢?
public static void main(String[] args) { String x = new String("ab"); change(x); System.out.println(x); } public static void change(String x) { x = "cd"; }
String不是基本對(duì)象所以String是引用傳遞。但是這里的引用傳遞知識(shí)傳遞String引用的地址 .當(dāng)執(zhí)行x=cd是原來ab的對(duì)象還在JVM中。外部x的引用地址沒有變 。 變得知識(shí)change方法中x的指向。所以外部打印的還是ab
以上就是分析Java中為什么String不可變的詳細(xì)內(nèi)容,更多關(guān)于Java中為什么String不可變的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
后端返回各種圖片形式在前端的轉(zhuǎn)換及展示方法對(duì)比
這篇文章主要給大家介紹了關(guān)于后端返回各種圖片形式在前端的轉(zhuǎn)換及展示方法對(duì)比的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2023-06-06SpringBoot中使用Servlet三大組件的方法(Servlet、Filter、Listener)
這篇文章主要介紹了SpringBoot中使用Servlet三大組件的方法(Servlet、Filter、Listener),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-01-01maven多個(gè)倉(cāng)庫(kù)查詢的優(yōu)先級(jí)順序案例講解
這篇文章主要介紹了maven多個(gè)倉(cāng)庫(kù)查詢的優(yōu)先級(jí)順序,考慮到我們常用的配置文件是conf/settings.xml和工程里面的pom.xml文件,我們針對(duì)這兩個(gè)文件的結(jié)合來分析倉(cāng)庫(kù)的使用順序,需要的朋友可以參考下2023-04-04Spring Boot3.x自動(dòng)配置不生效的排查與解決方法(IDEA 文件夾命名導(dǎo)致的問題)
在SpringBoot多模塊項(xiàng)目中,自動(dòng)配置類未生效的問題通常源于文件路徑錯(cuò)誤,通過檢查和修正AutoConfiguration.imports文件的實(shí)際路徑,可以解決自動(dòng)配置不生效的問題,感興趣的朋友跟隨小編一起看看吧2024-11-11Spring中的BeanFactory與FactoryBean區(qū)別詳解
這篇文章主要介紹了Spring中的BeanFactory與FactoryBean區(qū)別詳解,BeanFactory是一個(gè)接口,它是spring中的一個(gè)工廠,FactoryBean也是一個(gè)接口,實(shí)現(xiàn)了3個(gè)方法,通過重寫其中方法自定義生成bean,需要的朋友可以參考下2024-01-01使用Java和WebSocket實(shí)現(xiàn)網(wǎng)頁(yè)聊天室實(shí)例代碼
WebSocket是HTML5一種新的協(xié)議,它實(shí)現(xiàn)了瀏覽器與服務(wù)器全雙工通信,這里就將使用WebSocket來開發(fā)網(wǎng)頁(yè)聊天室,對(duì)Java和WebSocket實(shí)現(xiàn)網(wǎng)頁(yè)聊天室的實(shí)例代碼感興趣的朋友一起學(xué)習(xí)吧2016-06-06java集合框架的體系結(jié)構(gòu)詳細(xì)說明
最近在一本J2EE的書中看到了很不錯(cuò)的對(duì)集合框架的說明文章2012-11-11