Strings="a"和newString("a"),有很大區別,你知道嗎?

一般對象都是通過 new 關鍵字生成的,但是 String還有第二種生成方式,也就是我們經常使用的直接申明方式,比如:String str = "a",即是通過直接量 "a"進行賦值的。對於String 對象來說,這種方式是極力推薦的,但不建議使用 new String("a")的方式賦值。為什麼呢?

我們來看一段程序:

注意看上邊的程序,我們使用 "==" 判斷的是兩個對象的引用地址是否相同,也就是判斷是否為同一個對象,列印結果是true,fasle,true。即有兩個直接量是同一個對象(經過intern處理后的String與直接量是同一個對象),但是直接通過new 生成的對象卻與之不相等,原因何在?

原因是Java 為了避免在一個系統中大量產生 String 對象(為什麼會大量產生?因為String字元串是程序中最經常使用的類型),於是就設計出了一個字元串池(也叫做字元串常量池,String Pool 或 StringConstant Pool 或 String Literal Pool),在字元串池中所容納的都是 String字元串對象,它的創建機制是這樣的:

創建一個字元串時,首先檢查池中是否有字面值相等的字元串,如果有,則不再創建,直接返回池中該對象的引用,若沒有則創建,然後放到池中,並返回新建對象的引用,這個池和我們平常所說的池概念非常相似。對於此例子來說,就是在創建第一個"中國"字元串時,先檢查字元串池中有沒有該對象,發現沒有,於是就創建了"中國"這個字元串並放到池中,待在創建str2字元串時,由於池中已經有了該字元串,於是就直接返回了該對象的引用,此時,str1和 str2 指向的是同一個地址,所以使用 "==" 來判斷那當然是相等了。

那為什麼使用 new String("中國") 就不相等了呢?因為直接聲明一個 String對象是不檢查字元串池的,也不會吧對象放到池中,那當然 "==" 為 false 了。

那為什麼使用 intern 方法處理后就又相等了呢?因為 intern會檢查當前的對象在對象池中是否有字面值相同的引用對象,如果有則返回池中對象,如果沒有則放置到對象池中,並返回當前對象。

可能有碼農同學要問了,對象放到池中會不會產生線程安全問題呀?好問題,不過Java已經考慮到了,String類是一個不可變對象其實有兩層意思:一是 String 類 是 final類,不可繼承,不可能產生一個 String的子類;二是在String 類提供的所有方法中,如果有String返回值,就會新創建一個String對象,不對原對象進行修改,這也就保證了原對象是不可改變的。

通過上邊的介紹,我們發現 Java在字元串的創建方面確實提供了非常好的機制,利用對象池不僅可以提高效率,同時也減少了內存空間的佔用,建議大家在開發中使用直接量賦值方式,除非確有必要才新建立一個String對象。

你可能會喜歡