String字串的認識
1. 簡單認識String字串
通過原始碼我們可以看出String字串被final進行修飾,那麼也就說明了String字串不能被繼承和重寫。
String的特點:不能繼承和重寫
關於字串與記憶體關係:
String str1 = new String("abc"); (1)
String str2 = "abc"; (2)
String str3 = "a" + "bc"; (3)
String str4 = "a" + new String("bc"); (4)
分析:
從1式可以看出:會產生兩個記憶體空間,在堆記憶體申請一份,然後在常量池裡面申請一份,然後棧記憶體變數str1指向堆記憶體。
從2式可以看出:str2會在常量池裡面找,如果有的話,就不申請記憶體空間,如果沒有的話,需要在常量池申請記憶體。
從3式可以看出 : jvm對用“+”進行連線的字串進行了優化,它的思想和str2內容差不多。
從4式可以看出:它進行new操作,然後進行拼接,這樣的話申請的記憶體地址空間是不同的。
常量池:就是在編譯器被確定,儲存在編譯的。class檔案中,主要有類,方法,介面的常量組成,以及字串常量等。常量池還具備動態性,執行期間可以將新的常量放入池中,例如呼叫String的intern()方法。
從上述我們可以提出問題堆記憶體的物件和常量池裡面的物件有什麼關係?
根據上述1式可以看出,應該是把堆記憶體的內容克隆一份去常量池中。
String常用方法的介紹:
replace方法:
1.把原來字串變為字元陣列
2.判斷要替換的字元和新字元是否相等,如果相等就返回原來的內容,不相等,則進行替換操作
3.找到要替換字元的位置
4.然後產生一個新陣列,把替換字元位置之前的字母裝到這個新數組裡面
5.在遍歷替換字元位置之後的內容,如果value[i] 和oldchar相等的話,就變為newChar
6.最後把這個字元陣列變為字串
分析:這是jdk1.7原始碼的內容(
indexof 方法:
indexof引數說明:
Soure | 原始字串 |
sourceOffset | 原始字串偏移大小 |
sourceCount | 原始字串個數 |
target | 目標字串 |
targetOffset | 目標字串偏移大小 |
fromIndex | 起始下標 |
1. 用起始下標(fromIndex)和原始字串大小進行進行比較
2. 取出目標的第一個元素,這個取出時根據targetOffset的下標來取得
3. 用target[targetOffset]的值,在原始字串找與之對應的值。
4. 如果在原始字串裡面找過一遍沒有的話,就返回-1
5. 如果找到的話,就需要記住這個下標的位置 j = i+1
6. 然後用這下標j取出source[j]和taget[targetOffet+1]進行比較,如果符合條件就返回i下標
分析:假設讓我們去實現首先取出目標字串第一個元素,然後用這個元素和原始字串的每一個進行比較,如果沒有找到的話,就返回-1,找到的話,記錄目標元素在原始字串位置,然後從這個元素開始進行逐一比較。,如果目標元素都和原始元素比較結束,並且都符合條件,返回原來儲存的下標i。(其實和jdk原始碼思想大致相同,現在糾結的是,為啥原始碼裡面有這麼多引數)
trim方法:
1. 得到開始下標st
2.得到為節點下標leng
3. 得到value[st] 不為空字串的下標
4. 得到value[length]不為空字串下標
5.最後用str.substring()進行擷取。
分析:假設讓我們去做,我們可以提供出幾種方式呢
簡單說一下String,StringBuffer和StringBuilder之間的區別?
String是字串常量,StringBuffer和StringBuilder是字串變數
每一次對字串常量進行操作時,都會產生新的物件,如果頻繁對字元創進行改變,這樣會產生對系統的效能的影響。
但是有一個特殊操作,例如 String str = “a” + “b”;有人會說這樣並沒有頻繁產生物件,這是因為常量池對“+”進行特殊處理(如何進行處理,現在還在研究中),但是這樣的就比較耗效能,String str1 = “a” String str2 = ’‘b“ String str3 = str1 +str2;
StringBuffer 保證執行緒安全,那麼它使用與多執行緒環境中
StringBuilder適應單執行緒環境中字串緩衝區(這裡面的字串緩衝區如何設計還在研究中)