摘要:但是通過構(gòu)造函數(shù)的并不是。通過構(gòu)造函數(shù)創(chuàng)建的變量在機(jī)制上與其他對(duì)象一致,都是在上創(chuàng)建新的對(duì)象,然后把引用賦給變量。此外,的方法和等方法實(shí)現(xiàn)均是調(diào)用了構(gòu)造函數(shù)創(chuàng)建了新的對(duì)象,所以他們返回的也都是存在于上的新對(duì)象。
String經(jīng)常在一個(gè)語言中或多或少都有些特殊地位。在Java亦不例外。今天先來討論,String是不可變的。
String是引用類型,String變量?jī)?chǔ)存一個(gè)地址,地址指向內(nèi)存堆中的String對(duì)象。當(dāng)我們說變量不可變,有兩種不可變性:
變量?jī)?chǔ)存的地址不可變;
地址指向的對(duì)象內(nèi)容不可變。
String的不可變指的是哪一種?下面用例子來看。
通常有人在疑問String不可變時(shí),會(huì)舉這樣的例子:我們平時(shí)不都像下面這樣在“修改”String字符串嗎:
String s = "hello,world"; s = "Hello,coder"; System.out.println(s); //Hello,coder
我認(rèn)為這只是一個(gè)語義上的誤導(dǎo)。賦值操作符=通常作用于基本數(shù)據(jù)類型時(shí),確是修改變量的值。所以在這里讓人誤以為也是修改了變量的內(nèi)容。但是對(duì)于引用類型String,s="Hello,coder"的實(shí)際作用是將變量s指向另一個(gè)內(nèi)容為Hello,coder的新的對(duì)象。
所以,對(duì)于String不可變性的結(jié)論顯而易見了:String變量指向的地址是可變的,他的不可變性當(dāng)然說的是第二種——地址指向的對(duì)象內(nèi)容不可變。
縱覽String的方法,String類確實(shí)沒有提供能從String外部修改對(duì)象的方法。我們熟悉的replace,substring等等方法都要返回一個(gè)String,其實(shí)都是在返回一個(gè)新的對(duì)象,而沒有修改原有的對(duì)象。
為什么要設(shè)計(jì)成對(duì)象內(nèi)容不可變?
String常量池一個(gè)說法是便于實(shí)現(xiàn)String常量池。String存在于常量池中,當(dāng)新創(chuàng)建一個(gè)字符串變量,如果字符串在內(nèi)存中已經(jīng)存在,那么就會(huì)把這個(gè)已經(jīng)存在于常量池對(duì)象的地址賦給變量。這樣可節(jié)省內(nèi)存開銷。
但這不完全對(duì)。
只有兩種情況下創(chuàng)建的String變量,他們才會(huì)指向常量池中的同一對(duì)象:
String是字面直接量賦值創(chuàng)建。字面直接量是編譯期常量,變量會(huì)指向常量池中的對(duì)象。所有字面量賦值創(chuàng)建的String變量都會(huì)指向常量池中的對(duì)象。
通過String類的intern()方法得到String變量也是指向常量池中的對(duì)象。
但是通過構(gòu)造函數(shù)new String()的并不是。通過構(gòu)造函數(shù)創(chuàng)建的String變量在機(jī)制上與其他對(duì)象一致,都是在heap上創(chuàng)建新的對(duì)象,然后把引用賦給變量。
簡(jiǎn)單例子驗(yàn)證。
String a = "hello,world"; String b = "hello,world"; boolean c = (a == b); //true String d = new String("hello,world"); String e = new String("hello,world");; boolean f = (d == e); //false String g = d.intern(); boolean h = (a == g); //true
此外,String的方法substring,relpace和split等方法實(shí)現(xiàn)均是調(diào)用了構(gòu)造函數(shù)創(chuàng)建了新的對(duì)象,所以他們返回的String也都是存在于heap上的新對(duì)象。
綜上來看似乎節(jié)省不了多少內(nèi)存,畢竟程序中編譯常量是少數(shù),大多數(shù)String都是在運(yùn)行時(shí)產(chǎn)生。
線程安全這一點(diǎn)顯而易見,對(duì)象內(nèi)容都不可變了,自然不會(huì)有線程安全問題。
代碼安全String經(jīng)常被用來存儲(chǔ)server connection, database connection或者file path等等。如果String可變,一旦代碼某處改動(dòng)了字符串,會(huì)對(duì)系統(tǒng)有安全和穩(wěn)定性威脅。發(fā)生在其他普通字符串,則是不可預(yù)料的bug。尤其是代碼復(fù)雜度很高的時(shí)候,一個(gè)字符串對(duì)象被多個(gè)變量引用,直接修改對(duì)象內(nèi)容,引起所有引用該對(duì)象的變量都發(fā)生變化,容易引起bug。
當(dāng)然這一點(diǎn)主要是降低程序員的錯(cuò)誤和bug的可能。
其實(shí),話說回來,在JAVA里,String不可變也并非特殊,所有包裝類Interger,Boolean等都是不可變類。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/77028.html
摘要:文本已收錄至我的倉庫,歡迎記錄一次在寫代碼時(shí)愚蠢的操作,本文涉及到的知識(shí)點(diǎn)不可變性一交代背景我這邊有一個(gè)系統(tǒng),提供一個(gè)接口去發(fā)送短信。 前言 只有光頭才能變強(qiáng)。文本已收錄至我的GitHub倉庫,歡迎Star:https://github.com/ZhongFuCheng3y/3y 記錄一次在寫代碼時(shí)愚蠢的操作,本文涉及到的知識(shí)點(diǎn):String不可變性 一、交代背景 我這邊有一個(gè)系統(tǒng),...
摘要:的不變性,如下圖所示,當(dāng)你改變了的之后指向了一個(gè)新的對(duì)象原對(duì)象不做改變。但其引用的數(shù)組是可變的。所以的不可變性的關(guān)鍵并不是的作用。同時(shí)編寫者為了避免因?yàn)榈牟豢勺冃詫?dǎo)致占用大量空間,為此設(shè)計(jì)了字符串常量池 在貓眼的面試中被面試官問到為什么String的字符串是不變的。當(dāng)時(shí)我的回答是因?yàn)镾tring類是用final關(guān)鍵字修飾的,當(dāng)被問到為什么用 final修飾就是不可變的時(shí)候我發(fā)現(xiàn)自己說的...
摘要:所有變量的類型在編譯時(shí)已知在程序運(yùn)行之前,因此編譯器也可以推導(dǎo)出所有表達(dá)式的類型。像變量的類型一樣,這些聲明是重要的文檔,對(duì)代碼讀者很有用,并由編譯器進(jìn)行靜態(tài)檢查。對(duì)象類型的值對(duì)象類型的值是由其類型標(biāo)記的圓。 大綱 1.編程語言中的數(shù)據(jù)類型2.靜態(tài)與動(dòng)態(tài)數(shù)據(jù)類型3.類型檢查4.易變性和不變性5.快照?qǐng)D6.復(fù)雜的數(shù)據(jù)類型:數(shù)組和集合7.有用的不可變類型8.空引用9.總結(jié) 編程語言中的數(shù)據(jù)...
摘要:這兩個(gè)操作符都是編譯器默認(rèn)引入了類,最后都調(diào)用方法返回對(duì)象,臨時(shí)對(duì)象被回收,因此效率極為低下 Java String類筆記 聲明 文章均為本人技術(shù)筆記,轉(zhuǎn)載請(qǐng)注明出處https://segmentfault.com/u/yzwall String的不可變性 String的不可變性 // String declaration public final class String ...
摘要:性能當(dāng)字符串是不可變時(shí),字符串常量池才有意義。字符串常量池的出現(xiàn),可以減少創(chuàng)建相同字面量的字符串,讓不同的引用指向池中同一個(gè)字符串,為運(yùn)行時(shí)節(jié)約很多的堆內(nèi)存。 在學(xué)習(xí)Java的過程中,我們會(huì)被告知 String 被設(shè)計(jì)成不可變的類型。為什么 String 會(huì)被 Java 開發(fā)者有如此特殊的對(duì)待?他們的設(shè)計(jì)意圖和設(shè)計(jì)理念到底是什么?因此,我?guī)е韵氯齻€(gè)問題,對(duì) String 進(jìn)行剖析: ...
閱讀 871·2023-04-26 00:11
閱讀 2668·2021-11-04 16:13
閱讀 2118·2021-09-09 09:33
閱讀 1485·2021-08-20 09:35
閱讀 3842·2021-08-09 13:42
閱讀 3617·2019-08-30 15:55
閱讀 1080·2019-08-30 15:55
閱讀 2232·2019-08-30 13:55