文章目錄
- 前言
- 1.創建字串
- 2.字串比較相等
- 2.1字串傳參
- 3.字串常量池
- 4.字串創建實體分析
- 5.理解字串不可變
- 6.字符, 位元組與字串
- 6.1字符與字串
- 6.2位元組與字串
- 7.字串常見操作
- 7.1字串比較
- 7.2字串查找
- 7.3字串替換
- 7.4字串拆分
- 7.5字串截取
- 7.6其他操作
- 8. StringBuffer 和 StringBuilder
- 8.1String 和 StringBuffer 和StringBuilder的區別
- 8.2StringBuffer 和 StringBuilder的區別:
前言
java是面向物件的一門編程語言,通過實體化物件,物件間的互動實作相應的功能,決解相應的問題,,java中實作了很多的類供我們使用,我們要學習java一定要學好一些常用的類,去學習里面的構造方法,成員方法,介面方法等,所以今天我就簡單的向大家介紹String類,和類里面的一些構造方法及常用的方法,首先我打開java使用幫助檔案,針對的是JDK1.8版本,看檔案對Sting這個類的介紹,這里簡單的說明了Sting這個類是在java.lang這個包底下的,它繼承了object類,以及這個類實作了哪些介面,有哪些構造方法等許多的描述,我們有時間可以多多閱讀這個中文幫助檔案,在使用其他的類有什么不明白的也可以查閱該檔案,

1.創建字串
🎇常見的構造 String 的方式:
public static void main(String[] args) {
// 方式一
String str1 = "hellobit";
System.out.println(str1);
// 方式二
String str2 = new String("hellobit");
System.out.println(str2);
// 方式三
char[] chars = {'a','b','c'};
String str3 = new String(chars);
System.out.println(str3);
}
??方式三String里面重寫了toString方法,再通過println進行列印,就列印了str3這個參考所指向的物件了,所以這里列印的是字串的內容,而不是參考里面的地址,對于字串的創建,我們需要重點理解創建時的記憶體布局情況,這樣可以幫助我們更好地理解字串的創建,方式一,方式二創建字串的記憶體布局比較簡單,直接就是堆疊上的參考變數指向堆上的物件,后面有構造String的記憶體布局圖,接下來我簡單地畫一下方式三創建字串的記憶體布局圖,

首先我們在堆區創建一個字符陣列,由參考變數chars來指向它,之后我們再new了一個物件String(chars),物件里面的成員變數有一個char型別的陣列value,value是一個參考變數,構造這個匿名物件的時候我們要傳一個引數,引數是陣列或者字串都行,呼叫String的其中一個構造方法public String(char value[]) {
this.value = Arrays.copyOf(value, value.length);
}該方法復制產生了一個新的陣列,這個陣列由value這個參考來維護,
2.字串比較相等
??📃如果現在有兩個int型變數,判斷其相等可以使用 == 完成,
int x = 10 ;
int y = 10 ;
System.out.println(x == y);
// 執行結果
true
如果說現在在String類物件上使用 == ?
代碼1
String str1 = "Hello";
String str2 = "Hello";
System.out.println(str1 == str2);
// 執行結果
true
看起來貌似沒啥問題, 再換個代碼試試, 發現情況不太妙.
代碼2
String str1 = new String("Hello");
String str2 = new String("Hello");
System.out.println(str1 == str2);
// 執行結果
false
代碼一的記憶體布局:

代碼二的記憶體布局:

📝📐我們來分析上面兩種創建 String 方式的差異.我們發現, 代碼1中str1 和 str2 是指向同一個物件的. 此時如 “Hello” 這樣的字串常量是在 字串常量池 中,代碼2中str1 和 str2 是指向的不是同一個物件,但最終指向的字串內容都是 “Hello” ,通過 String str1 = new String(“Hello”); 這樣的方式創建的 String 物件相當于再堆上另外開辟了空間來存盤"Hello" 的內容, 也就是記憶體中存在兩份 “Hello”.
🔍?? String 是參考資料型別,如果使用“==”來比較兩個參考的值,比較的還是值相同不相同,但是這個值不是字串值,是參考值,str1和str2分別指向堆上兩個不同地址處,代碼2 str1和str2的值不同,所以結果為false,如果要比較字串的內容可以使用equals方法進行比較,上圖中代碼2首先第一行代碼傳入字串"Hello",發現字串常量池里面沒有該字串,就將其入池,value是String里面的一個陣列參考,是new產生的匿名物件的一個成員,new String("Hello")產生物件時要傳入一個引數Hello,傳入引數后呼叫構造方法,這樣Srting字串才能完成構造,這樣value這個參考指向了字串常量池里面的"Hello",str1指向value,同理str2也指向它創建的物件的成員value,創建物件時也要傳入引數Hello,但發現常量池里面有Hello了就直接用了,value就直接指向常量池里面唯一的那個Hello了,
String str1 = new String("Hello");
String str2 = new String("Hello");
System.out.println(str1.equals(str2));
// System.out.println(str2.equals(str1)); // 或者這樣寫也行
// 執行結果
true
equals 使用注意事項
現在需要比較 str 和 “Hello” 兩個字串是否相等, 我們該如何來寫呢?
String str = new String("Hello");
// 方式一
System.out.println(str.equals("Hello"));
// 方式二
System.out.println("Hello".equals(str));
在上面的代碼中, 哪種方式更好呢????
🎇🎆那推薦使用 “方式二”. 一旦 str 是 null, 方式一的代碼會拋出例外, 而方式二不會,
String str = null;
// 方式一
System.out.println(str.equals("Hello")); // 執行結果 拋出 java.lang.NullPointerException 異
常
// 方式二
System.out.println("Hello".equals(str)); // 執行結果 false
2.1字串傳參
Java 中陣列, String, 以及自定義的類都是參考型別,由于 String 是參考型別, 因此對于以下代碼,我們應該注意傳參考不一定改變字串的值,
String str1 = "Hello";
String str2 = str1;
它的記憶體布局圖如上面代碼1,, 這時我們可能會想是不是修改 str1 , str2 也會隨之變化呢?
str1 = "world";
System.out.println(str2);
// 執行結果
Hello

我們發現, “修改” str1 之后, str2 也沒發生變化, 還是 hello?
事實上, str1 = “world” 這樣的代碼并不算 “修改” 字串, 而是讓 str1 這個參考指向了一個新的 String 物件.
在如下面的代碼:
public static void func(String str) {
str = "bit";
}
public static void main(String[] args) {
String str = "gaobo";
func(str);
System.out.println(str);
}
下面的代碼在函式傳參的時候,傳參考不會改變原來的值

這里有兩個參考,一個main函式里面的,一個func函式里面的,開始的時候這兩個參考指向同一記憶體空間0x123,之后被調函式里的參考指向一個新的地址,但不影響呼叫函式里的參考,
3.字串常量池
在上面的例子中, String類的兩種實體化操作, 直接賦值和 new 一個新的 String.
直接賦值
String str1 = "Hello";
String str2 = "Hello";
System.out.println(str1 == str2);
// 執行結果
true
🎇為什么現在并沒有開辟新的堆記憶體空間呢??因為String類的設計使用了共享設計模式
在JVM底層實際上會自動維護一個物件池(字串常量池)
- 如果現在采用了直接賦值的模式進行String類的物件實體化操作,那么該實體化物件(字串內容)將自動保存 到這個物件池之中.
- 如果下次繼續使用直接賦值的模式宣告String類物件,此時物件池之中如若有指定內容,將直接進行參考,
- 如若沒有,則開辟新的字串物件而后將其保存在物件池之中以供下次使用 也就是簡單地說該字串常量池中只會有不同的String類物件,不會出現相同的String類物件,常量池的一個功能幫助我們節省記憶體空間,同樣的東西我們存盤一份就行了,
采用構造方法
String str1 = new String("Hello");
String str2 = new String("Hello");
System.out.println(str1 == str2);
// 執行結果
false
📝由上面的代碼二的記憶體布局圖可知:
這樣的做法有兩個缺點:
- 如果使用String構造方法就會開辟兩塊堆記憶體空間,并且其中一塊堆記憶體將成為垃圾空間(字串常量 “hello” 也是一個匿名物件, 用了一次之后就不再使用了, 就成為垃圾空間, 會被 JVM 自動回收掉).
- 字串共享問題. 同一個字串可能會被存盤多次, 比較浪費空間
4.字串創建實體分析
下面我將通過一些簡單的例子,進一步地帶老鐵們熟悉直接賦值,采用構造方法構造字串及字串常量池在構造字串時的作用,
代碼1:
String str1 = "helloboy";
String str2 = new String("helloboy");
System.out.println(str1 == str2);//false
//比較的還是值相同不相同,但是這個值不是字串值,是參考值
System.out.println(str1.equals(str2));//true
記憶體布局圖:

📝該代碼的記憶體布局圖,可以結合最上面上面代碼1,代碼2的記憶體布局圖來看,首先直接賦值創建了一個字串 String str1 = “helloboy”;,放在字串常量池,之后通過構造的方式,str2指向在堆區實體化的物件,這個物件的產生需要傳一個字串引數,剛好字串常量池有這個引數,,直接用就行了,value就指向了這個引數,
代碼2:
String str1 = "hello";
String str2 = "hello" + "world";
System.out.println(str1 == str2);//true
像"helloworld",“world”,"hello"這些量被稱為字串字面值常量,是一個常量,代碼在進行字串的拼接的時候,編譯期間會進行優化,把它優化為一個常量,由常量池的知識可知在運行期間就只開辟一塊空間存盤優化過的常量了,因此str1和str2就指向了字串常量池的同一塊空間了,
代碼3:
String str1 = "goodboy";
String str2 = "good";
String str3 = str2+"boy";
System.out.println(str1 == str3);

直接賦值構造兩個字串,“goodboy”,"good"放在字串常量池中,str1和str2分別指向這兩個字串,定義變數str3在堆區開辟空間,它的內容等于str2+“boy”;,str3最終指向拼接好的字串,
代碼4:
String str1 = "goodboy";
String str4 = "good"+new String("boy");
System.out.println(str1 == str4);

??📘"goodboy","good","boy"這些字串之前沒有的首先都是放入常量池,new String(“boy”)新產生一個物件,物件里的參考指向傳入的引數,之后在堆上開辟一塊記憶體,存拼接好的字串"goodboy",拼接好的字串雖然也是"goodboy",但是和常量池里的不一樣,
代碼5:
String str1 = "goodboy";
String str5 = new String("good)+new String("boy");
System.out.println(str1 == str5);//false
System.out.println(str1.equals(str5));//ture
這代碼和上面的差不多,用腳指頭想想也明白,哈哈!!(借助上面的代碼和圖秒懂),首先常量池里放入"goodboy",“good”,“boy”,通過構造的方式在堆區構造兩個字串,之后兩個字串在堆區拼接形成和常量池內容一樣的字串,str5指向該字串,
代碼6:
String str1 = "goodboy";
String str2= new String("goodboy");
str2.intern();
System.out.println(str1 == str2);

📝這個代碼和代碼1的記憶體布局圖一樣,只是多了一步對字串的入池操作 str2.intern();對于我們在堆區構造產生的字串,str2
拿到物件里面的字串的值,和常量池里面的字串比較,如果常量池有該字串就不如池,如果沒有該字串就把該字串放入常量池中,因為原來字串常量池里有我們構造出來的字串,所以堆區的字串就不如池了,記憶體代碼布局就像開始一樣的、
代碼7:
String s3 = new String("1") + new String("1");
s3.intern();
String s4 = "11";
System.out.println(s3 == s4);//true

上面的代碼是字串要入池的時候,池子里有該字串,現在的這個代碼是入池的時候,池子里沒有這個字串,首先在堆上創建兩個字串物件,之后拼接形成字串“11”,s3這個參考指向指向“11”,之后將s3指向的字串做入池操作,池子里沒有就入進去,入的時候在常量池里面開辟一塊記憶體,存盤要入的字串在堆疊區的地址,而不是內容,之后又創建一個物件“11”,因為產量池里面有這個物件,所以s4這個參考就直接存盤了常量池里那個字串的地址了,文字和上面的圖一起食用效果更佳!!!
代碼8:
String s3 = new String("1") + new String("1");
String s4 = "11";
s3.intern();
System.out.println(s3 == s4);

這代碼和上面的代碼只是有幾行代碼顛倒了,就產生了不一樣的效果了,s3在s4放入常量池后再入池,就入不了池了,就什么操作也不發生,
5.理解字串不可變
🌈?字串是一種不可變物件. 它的內容不可改變.
從源代碼可知String 類的內部實作也是基于一個 char value[]的陣列來實作的,這個陣列被final和private修飾 但是 String 類并沒有提供 set 方法來修改內部的字符陣列,所以簡單的認為字串是一種不可變物件,

感受下形如這樣的代碼
String str = "hello" ;
str = str + " world" ;
str += "!!!" ;
System.out.println(str);
// 執行結果
hello world!!!
形如 += 這樣的操作, 表面上好像是修改了字串, 其實不是. 記憶體變化如下:

從上面的記憶體變化圖中,我們可以看到,最終形成了一個新的字串,但是這個字串不是在原來字串的后面添加字串形成的,沒有修改字串的內容,是通過字串的拼接形成一個新的物件,第一次產生一個物件hello world并且str指向這個物件,第二次產生一個hello world!!!物件,str1又指向這個新的物件,每次拼接完成后,str這個參考里面的地址都發生了改變,
?🚫因此我們在開發中要注意不要出現類似如下的代碼,會產生大量的臨時物件, 效率比較低.
String str = "hello" ;
for(int x = 0; x < 1000; x++) {
str += x ;//拼接字串
}
System.out.println(str);
那么如果實在需要修改字串, 例如, 現有字串 str = “Hello” , 想改成 str = “hello” , 該怎么辦?
💯常見辦法: 借助原字串, 創建新的字串
substring()方法截取一個字串的子串,括號里面的引數表示從主串的什么位置開始截取,主串的第一個位置默認為0位置,之后又進行字串的截取,那么情況就和上面的情況一樣了,
String str = "Hello";
str = "h" + str.substring(1);//
System.out.println(str);
// 執行結果
hello
?特殊辦法: 使用 “反射” 這樣的操作可以破壞封裝, 訪問一個類內部的 private 成員,但今天的這篇博文我們不詳講,只是提一下,后面我的博文會詳細講到,
為什么 String 要不可變?(不可變物件的好處是什么?) ??
- 方便實作字串常量池. 如果 String 可變, 那么物件池就需要考慮何時深拷貝字串的問題了.
- 不可變物件是執行緒安全的.
- 不可變物件更方便快取 hash code, 作為 key 時可以更高效的保存到 HashMap 中.
6.字符, 位元組與字串
6.1字符與字串
字串內部包含一個字符陣列,String 可以和 char[] 相互轉換.
字符與字串常用的一些方法如下表:
| No | 方法名稱 | 型別 | 描述 |
|---|---|---|---|
| 1 | public String(char value[]) | 構造 | 將字符陣列中的所有內容變為字串 |
| 2 | public String(char value[], int offset, int count) | 構造 | 將部分字符陣列中的內容變為字串,offset 為偏移量,從0開始 ,count為轉換的字符個數 |
| 3 | public char charAt(int index) | 普通 | 取得指定索引的字符,索引從0開始 |
| 4 | public char[] toCharArray() | 普通 | 將字串變為字符陣列回傳 |
方法代碼簡單演示:
方法一:將字符陣列中的所有內容變為字串
char[] value = {'a', 'b', 'c', 'd', 'e'};
String str = new String(value);
System.out.println(str);
結果為:abcde
方法二:將部分字符陣列中的內容變為字串
char[] value = {'a','b','c','d','e'};
String str = new String(value,1,2);
//從偏移量為1的位置開始取2個字符來構造String物件
System.out.println(str);
結果為:bc
方法三: 取得指定索引的字符,索引從0開始
String str2 = "hello";
char ch = str2.charAt(1);//字串的第一個字符為0位置
System.out.println(ch);
結果為:e
方法四:將字串變為字符陣列回傳
String str3 = "hello";
char[] chars = str3.toCharArray();//將字串以字符陣列的方式進行存盤
System.out.println(Arrays.toString(chars));
結果為:[h,e,l,l,o]
???注意:對于上述方法給定的數字位置和數字范圍,一定要合理,不然就會產生例外,
6.2位元組與字串
位元組常用于資料傳輸以及編碼轉換的處理,字串 String 也能和位元組陣列 byte[] 相互轉換
| No | 方法名稱 | 型別 | 描述 |
|---|---|---|---|
| 1 | public String(byte bytes[]) | 構造 | 將位元組陣列變成字串 |
| 2 | public String(byte bytes[], int offset, int length) | 構造 | 將部分位元組陣列中的內容變為字串 |
| 3 | public byte[] getBytes() | 普通 | 將字串以位元組陣列的形式回傳 |
| 4 | public byte[] getBytes(String charsetName)throws java.io.UnsupportedEncodingException | 普通 | 編碼轉換處理 |
方法代碼簡單演示:
方法一:將位元組陣列變成字串
byte[] bytes = {97, 98 ,99 ,100};
String str = new String(bytes);
System.out.println(str);
結果為:abcd
方法二:將部分位元組陣列中的內容變為字串
byte[] bytes = {97, 98 ,99 ,100};
String str = new String(bytes, 1, 2);
System.out.println(str);
結果為:bc
方法三:將字串以位元組陣列的形式回傳
public static void main(String[] args) {
String str = "abcde";
byte[] bytes = str.getBytes();
System.out.println(Arrays.toString(bytes));
}
結果為:[97, 98, 99, 100, 101]
方法四:編碼轉換處理(很少使用,了解即可)
public static void main(String[] args) throws UnsupportedEncodingException {
String str = "李敏敏";
byte[] bytes = str.getBytes("utf-8");//幾乎不用
System.out.println(Arrays.toString(bytes));
}
結果為:[-26, -99, -114, -26, -107, -113, -26, -107, -113]
如果我們將編碼方式“utf-8”,改為“gbk”則會有不同的結果
public static void main(String[] args) throws UnsupportedEncodingException {
String str = "李敏敏";
byte[] bytes = str.getBytes("gbk");//幾乎不用
System.out.println(Arrays.toString(bytes));
}
結果為:[-64, -18, -61, -12, -61, -12]
其實這個方法就是把我們給的字串,以我們指定的編碼規則轉換為位元組陣列的,編碼規則不同則轉換的內容不同,在utf-8中一個漢字占3個位元組,gbk中占一個位元組,
小結:
那么何時使用 byte[], 何時使用 char[] 呢?
- byte[] 是把 String 按照一個位元組一個位元組的方式處理, 這種適合在網路傳輸, 資料存盤這樣的場景下使用. 更適合針對二進制資料來操作.
- char[] 是把 String 按照一個字符一個字符的方式處理, 更適合針對文本資料來操作,尤其是包含中文的時候.
- 一個簡單粗暴的區分方式就是用記事本打開能不能看懂里面的內容. 如果看的懂, 就是文本資料(例如 .java 檔案), 如果看不懂, 就是二進制資料(例如 .class 檔案),
7.字串常見操作
7.1字串比較
上述介紹到 equals 可以比較字串是否相等,并且是區分大小寫的,而除了它,String 類還有其他比較字串的方法
| No | 方法名稱 | 型別 | 描述 |
|---|---|---|---|
| 1 | public boolean equals(Object anObject) | 普通 | 區分大小寫的比較 |
| 2 | public boolean equalsIgnoreCase(String anotherString) | 普通 | 不區分大小寫的比較 |
| 3 | public int compareTo(String anotherString) | 普通 | 比較兩個字串大小關系 |
方法代碼簡單演示:
方法一:區分大小寫的比較
String str1 = "hello";
String str2 = new String("Hello");
System.out.println(str1.equals(str2));
結果為:false
方法二:不區分大小寫的比較
String str1 = "hello";
String str2 = new String("Hello");
System.out.println(str1.equalsIgnoreCase(str2));
結果為:true
方法三: 比較兩個字串大小關系
String str1 = "hello";
String str2 = new String("hella");
System.out.println(str1.compareTo(str2));
結果為:14
在String類中compareTo()方法是一個非常重要的方法,比較規則大致是,都是以第一個字串為比較基準,首先比較字串長度,第一個字串的長度大于第二個字串的長度則回傳一個正數,長度相同回傳0,第一個的長度小于第二個的長度回傳一個負數,長度相同之后從前往后比較,字串里面第一個不相同的字符 的大小關系就是整個字串大小的關系,比較的回傳值也是和比較長度的回傳情況一樣的,
7.2字串查找
| No | 方法名稱 | 型別 | 描述 |
|---|---|---|---|
| 1 | public boolean contains(CharSequence s) | 普通 | 判斷一個字串是否存在 |
| 2 | public int indexOf(String str) | 普通 | 從頭開始查找指定字串的位置,查到了回傳位置的開始索引,查不到回傳-1 |
| 3 | public int indexOf(String str, int fromIndex) | 普通 | 從指定位置開始查找子字串位置 |
| 4 | public int lastIndexOf(String str) | 普通 | 由后向前查找子字串位置 |
| 5 | public int lastIndexOf(String str, int fromIndex) | 普通 | 從指定位置由后向前查找 |
| 6 | public boolean startsWith(String prefix) | 普通 | 判斷是否以指定字串開頭 |
| 7 | public boolean startsWith(String prefix, int toffset) | 普通 | 從指定位置開始判斷是否以指定字串開頭 |
| 8 | public boolean endWith(String suffix) | 普通 | 判斷是否以指定字串結尾 |
方法代碼簡單演示:
方法一:判斷一個字串是否存在
String str = "helloworld";
System.out.println(str.contains("hello"));
結果為:true
方法二:從頭開始查找指定字串的位置,查到了回傳位置的開始索引,查不到回傳-1
String str = "helloworld";
System.out.println(str.indexOf("world"));
結果為:5
方法三:從指定位置開始查找子字串位置
String str = "helloworldhelloworld";
System.out.println(str.indexOf("world", 6));
結果為:15
方法四:
由后向前查找子字串位置
String str = "helloworld";
System.out.println(str.lastIndexOf("world"));
結果為:5
方法五: 從指定位置由后向前查找
String str = "helloworld";
//System.out.println(str.lastIndexOf("world"));
System.out.println(str.lastIndexOf("world", 5));
結果為:5
方法六:判斷是否以指定字串開頭
String str = "helloworld";
System.out.println(str.startsWith("hello"));
結果為:true
方法七:從指定位置開始判斷是否以指定字串開頭
String str = "helloworld";
System.out.println(str.startsWith("hello", 2));
結果為:false
方法八:判斷是否以指定字串結尾
String str = "helloworld";
System.out.println(str.endsWith("world"));
結果為:true
7.3字串替換
String 類中也有方法將一個指定的新字串替換掉已有的字串資料
| No | 方法名稱 | 型別 | 描述 |
|---|---|---|---|
| 1 | public String replaceAll(String regex, String replacement) | 普通 | 替換所有的指定內容 |
| 2 | public String replaceFirst(String regex, String replacement) | 普通 | 替換首個內容 |
| 3 | public String replace(char oldChar, char newChar) | 普通 | 替換所有的指定字符 |
方法一: 替換所有的指定內容
將原來字串里面的某一字串替換為另一字串
String str = "ababcabcd";
String str3 = str.replaceAll("ab","gg");
System.out.println(str3);
結果為:ggggcggcd
方法二:替換首個內容
將字串的開始幾個字符替換為另外的幾個字符
String str = "ababcabcd";
String str4 = str.replaceFirst("ab","gg");
System.out.println(str4);
結果為:ggabcabcd
方法三:替換所有的指定字符
將字串中某一個字符全部替換為另一個新的字符
String str = "ababcabcd";
//替換 所有的字符
String str2 = str.replace('a','g');
System.out.println(str2);
結果為:ggabcabcd
7.4字串拆分
String 類中也有方法將一個完整的字串按照指定的分隔符劃分為若干子字串
| No | 方法名稱 | 型別 | 描述 |
|---|---|---|---|
| 1 | public String[] split(String regex) | 普通 | 將字串全部拆分 |
| 2 | public String[] split(String regex, int limit) | 普通 | 將字串部分拆分,該陣列長度就是 limit 極限 |
方法一:將字串全部拆分,只有一個引數的
String str = "ab#abc#abcd";
//以引數#進行分割
String[] strings = str.split("#");
for ( String s : strings) {
System.out.println(s);
}
結果為:
ab
abc
abcd
方法二:將字串部分拆分,該陣列長度就是 limit極限
String str = "ab#abc#abcd";
//以引數進行分割 引數不存在 不分割 , 第二個引數 是分割的極限組數
String[] strings = str.split("#",5);
for ( String s : strings) {
System.out.println(s);
}
結果為:
ab
abc
abcd
注意:以引數進行分割 ,引數不存在 不分割 , 第二個引數 是分割的極限組數,分割的陣列小于等于這個極限陣列,
方法三:拆分 IP 地址
拆分是特別常用的操作. 一定要重點掌握. 另外有些特殊字符作為分割符可能無法正確切分, 需要加上轉義,如分割Ip地址的點號就是一個特殊的運算子,要特殊處理,
String str = "192.168.1.1";
String[] strings = str.split("\\.");
for ( String s : strings) {
System.out.println(s);
}
結果:
192
168
1
1
🚭?注意事項:
- 字符"|","*","+“都得加上轉義字符,前面加上”".
- 而如果是".",那么就得寫成"\."
- 如果一個字串中有多個分隔符,可以用
"|"作為連字符.
7.5字串截取
| No | 方法名稱 | 型別 | 描述 |
|---|---|---|---|
| 1 | public String substring(int beginIndex) | 普通 | 從指定索引截取到結尾 |
| 2 | public String substring(int beginIndex, int endIndex) | 普通 | 截取部分內容 |
方法一:從指定索引截取到結尾
String str1 = "helloworld";
String str2 = str1.substring(5);
System.out.println(str2);
結果為:“world”
方法二:截取部分內容
String str1 = "helloworld";
String str2 = str1.substring(2,5);
System.out.println(str2);
結果為:“llo”
注意事項:
- 索引從0開始
- 截取的范圍為左閉右開, 如substring(2, 5) 表示包含 02號下標的字符, 不包含 5 號下標
7.6其他操作
除了上述的一些操作字串的方法,其實還有很多其他的方法,我們可以使用那個API檔案查看方法的使用,下面以表格的形式列舉其他一些常見的方法,沒有演示它的使用,老鐵們可以自己用用,🤓😎
| No | 方法名稱 | 型別 | 描述 |
|---|---|---|---|
| 1 | public String trim() | 普通 | 去掉字串中的左右空格,保留中間空格 |
| 2 | public String toUpperCase() | 普通 | 字串轉大寫 |
| 3 | public String toLowerCase() | 普通 | 字串轉小寫 |
| 4 | public native String intern() | 普通 | 字串入池操作 |
| 5 | public int length() | 普通 | 取得字串長度 |
| 6 | public boolean isEmpty() | 普通 | 判斷字串是否為空(空不是 null,而是長度為0) |
這里的方法就不一一展示示例了,如果大家能夠把上述字串的方法都記得的話,那么去做一些題目那真的可以說是更加輕松了,并且字串的方法不止這些,大家可以去 Java 的 api 中去查看學習,
8. StringBuffer 和 StringBuilder
8.1String 和 StringBuffer 和StringBuilder的區別
👀🔅String 和 StringBuffer 和StringBuilder有相同也有不同,其實 StringBuffer 和StringBuilder就是String的plus版本,是對String的一些完善,StringBuffer 和 StringBuilde幾乎沒差別,我們先以StringBuffer 為例討論前兩者的不同,再討論后兩者的不同,
1.String 和 StringBuffer 都可以產生字串,但產生的方式不一樣,前者即可以通過直接賦值的方式產生,也可以通過實體化物件的方式產生,
StringBuffer sb = new StringBuffer("hello");
//StringBuffer sb1 = "hello";//不可以
String sb2="hello";
String string =new String("hello");
2.在String中使用"+"來進行字串連接,但是這個操作在StringBuffer 類中需要更改為append()方法:
StringBuffer sb = new StringBuffer("hello");
sb.append("bit");
sb.append(1).append("!!!");
System.out.println(sb);
//===========================
String s = "hello";
s = s + "bit";
3.除了append()方法外,StringBuffer也有一些String類沒有的方法, 如字串反轉reverse()等,
4.String和StringBuffer最大的區別在于:String的內容無法修改,而StringBuffer的內容可以修改,頻繁修改字串的情況考慮使用StingBuffer,如之前的字串的拼接:
這個代碼之前說了它會產生很多的物件,我們它執行的匯編代碼時是通過StingBuffer對其進行優化的,但還是產生了好多物件,這也說明了String的局限性,如果直接使用StingBuffer就只產生了一個物件,就完成了字串的修改,
String str = "hello";
for(int i = 0;i < 10;i++) {
str = str + i;
}
System.out.println(str);
如果我們直接使用StringBuilder代碼改成下面的代碼不就高效和節省記憶體了嘛
String str = "hello";
StringBuilder sb = new StringBuilder();
sb.append(str);
for(int i = 0;i < 10;i++) {
///str = str + i;
sb.append(i);
}
str = sb.toString();
System.out.println(str);
我們也可以在結合記憶體布局圖和原始碼截圖大致理解下:

再進一步說就是String產生的物件不可以變,每次都要產生新物件,在新物件里進行拼接 StringBuilder產生的物件是可以變的,進行拼接時 ,我們在StringBuilder物件的字串里添字串,他每次回傳的都是當前物件,它只new了一個物件,沒動過常量池里面的字串,沒毛病吧!
8.2StringBuffer 和 StringBuilder的區別:
StringBuffer有關鍵字synchronized 修飾,采用同步處理,在進行當前的字串拼接時不會受到其它拼接的的影響,等當前拼接完成后才進行其他拼接,屬于執行緒安全操作;而StringBuilder未采用同步處理,會受到其他拼接的干擾,屬于執行緒不安全操作
🔅**注意:**String和StringBuffer類不能直接轉換,如果要想互相轉換,可以采用如下原則:
- String變為StringBuffer:利用StringBuffer的構造方法或append()方法
- StringBuffer變為String:呼叫toString()方法,
如下代碼:
以上兩種方式 就是 String轉換為StringBuilder、StringBuffer型別字串,
String str = "abcd";
StringBuilder sb = new StringBuilder(str);
StringBuilder sb2 = new StringBuilder();
sb2.append(str);
StringBuilder、StringBuffer型別字符轉換為String,(以StringBuilder為例)
StringBuilder sb2 = new StringBuilder("abc");
String s = sb2.toString();
System.out.println(s);
好了,本期有關String類的文章就介紹到這,下篇博文又見,感謝點贊的友友們,

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/306230.html
標籤:java
上一篇:StringBuffer類
