閱讀573 返回首頁    go 阿裏雲 go 技術社區[雲棲]


Java中的String不再糾結

先分享一下java中string的一些小專題吧,這部分比比較基礎,但是也非常的有用。我發現很多麵試官像中了邪一樣就愛問這個。。string的種種,糾結,希望這篇文章讓大家不再糾結。。

string是我們經常用到的一個類型,其實有時候覺得寫程序就是在反複的操作字符串,這是C的特點,在java中,jdk很好的封裝了關於字符串的操作。今天主要講的是三個類String 、StringBuffer 、 StringBuilder .這三個類基本上滿足了我們在不同情景下使用字符串的需求。

先說,第一個String。

JDK的解釋是 “Strings are constant; their values cannot be changed after they are created”也就是說String對象一旦被創建就是固定不變的了(你一定有問題,但請先等一等,耐心讀下去),這樣的一點好處就是可以多線程之間訪問,因為隻讀不寫。

一般情況下我們以下麵兩種方式創建一個String對象

1c6c0003d7093c757d1a

兩種方式是有區別的,這和java的內存管理有關,前麵已經說過,string創建之後是不可變的,所以按照第一種方式創建的字符串會放在棧裏,更確切的是常量池中,常量池就是用來保存在編譯階段確定好了大小的數據,一般我們定義的int等基本數據類型就保存在這裏。

其具體的一個流程就是,編譯器首先檢查常量池,看看有沒有一個“string”,如果沒有則創建。如果有的話,則則直接把str1指向那個位置。如果你想學習Java可以來這個群,首先是二二零,中間是一四二,最後是九零六,裏麵有大量的學習資料可以下載。

第二種創建字符串的方法是通過new關鍵字,還是java的內存分配,java會將new的對象放在堆中,這一部分對象是在運行時創建的對象。所以我們每一次new的時候,都會創建不同的對象,即便是堆中已經有了一個一模一樣的。

寫一個小例子

1c6c0003d7063bcc9f68

String str1 = "string";

1c6c0003d7063bcc9f68

這個的運行結果是

true //解釋:兩個字符串的內容完全相同,因而指向常量池中的同一個區域

false //解釋:每一次new都會創建一個新的對象

false // 解釋: 注意==比較的是地址,不僅僅是內容

true //介紹一下intern方法,這個方法會返回一個字符串在常量池中的一個地址,如果常量池中有與str3內容相同的string則返回那個地址,如果沒有,則在常量池中創建一個string後再返回。實際上,str3現在指向了str1的地址。

這就是讓人糾結的string了,現在你可以說話了。。。很多人有這樣的疑問就是既然string是不變的,那麼為什麼str1 + "some"是合法的,其實,每次對string進行修改,都會創建一個新的對象。

所以如果需要對一個字符串不斷的修改的話,效率是非常的低的,因為堆的好處是可以動態的增加空間,劣勢就是分配新的空間消耗是很大的,比如我們看下麵的測試。

1c6c0003d7063bcc9f68

long start = System.currentTimeMillis();

1c6c0003d7063bcc9f68

我的機器上運行結果是the run time is 3538 ms 如果你把循環的次數後麵再增加幾個0就會更慢。因為每一次循環都在創建心的對象,那麼JDK如何解決這個問題?

下麵就要說第二個類StringBuffer。

StringBuffer是一個線程安全的,就是多線程訪問的可靠保證,最重要的是他是可變的,也就是說我們要操作一個經常變化的字符串,可以使用這個類,基本的方法就是append(與string的concat方法對應)和insert方法,至於怎麼使用,就不多講了,大家可以自己查看API。

1c6c0003d7063bcc9f68

StringBuilder sb = new StringBuilder("string builder");

1c6c0003d7063bcc9f68

測試一下,這次隻需要8ms,這就是效率。

那麼接下來,就要問StringBuilder是幹什麼的,其實這個才是我們嚐使用的,這個就是在jdk 1.5版本後麵添加的新的類,前麵說StringBuffer是線程同步的,那麼很多情況下,我們隻是使用一個線程,那個同步勢必帶來一個效率的問題,StringBuilder就是StringBuffer的非線程同步的版本,二者的方法差不多,隻是一個線程安全(適用於多線程)一個沒有線程安全(適用於單線程)。

其實看了一下jdk源代碼就會發現,StringBuffer就是在各個方法上加上了關鍵字syncronized

1db70000ce639ae26ab8

以上就是對三個字符串類的一個總結,總之不要在這上麵糾結。。。。。。不想介紹太多的方法,總覺得那樣會把一篇博客弄成API文檔一樣,而且還非常的繁瑣。都是些體會,希望有所幫助。起碼不要再糾結,尤其是麵試。。。。

最後更新:2017-04-27 11:00:51

  上一篇:go CentOS6 安裝VSFTP及本地用戶模式
  下一篇:go Redis的三種啟動方式