天天看點

【JAVA中String、StringBuffer、StringBuilder類的使用】

一、String類概述

1.String對象一旦建立就不能改變。

2.字元串常量池。

字元串常量池的特點:池中有則直接使用,池中沒有則建立新的字元串常量。

例1:

1 public class StringDemo
 2 {
 3     public static void main(String args[])
 4     {
 5         StringDemo1();
 6 
 7     }
 8     public static void StringDemo1()
 9     {
10         String str1="abcd";
11         String str2="abcd";
12         System.out.println(str1==str2);
13     }
14 }      

View Code

以上的代碼運作結果為true。

原因分析:當運作到代碼String str1="abcd";處,JAVA虛拟機會先檢查字元串常量池中是有相同的字元串,如果有,則傳回該對象的引用,否則,新建立一個字元串并傳回該對象的引用。

運作到代碼String str2="abcd";的時候,JAVA虛拟機發現字元串常量池中有相同的字元串,是以不再建立而是傳回該對象的引用。

例2:

1 public class StringDemo
 2 {
 3     public static void main(String args[])
 4     {
 5         //StringDemo1();
 6         StringDemo2();
 7 
 8     }
 9     public static void StringDemo2()
10     {
11         String str1="abcd";
12         String str2=new String("abcd");
13         System.out.println(str1==str2);
14     }
15     public static void StringDemo1()
16     {
17         String str1="abcd";
18         String str2="abcd";
19         System.out.println(str1==str2);
20     }
21 }      

View Code

上述運作結果為false。

分析:運作完代碼String str1="abcd";的時候,字元串常量池中将會含有一個值為abcd的字元串;執行到代碼String str2=new String("abcd");時,進行了兩個動作,因為使用new方法建立字元串對象的時候,所需要的構造方法中需要一個對象來建立新對象,是以,"abcd"就是一個動作,它将會在字元串常量池中尋找相同值的對象并傳回該對象的引用。但是String類的構造方法中并沒有直接使用該對象,而是将該對象先轉換成一個字元數組,然後将該字元數組重新組裝成一個字元串對象。這個過程可以通過檢視源代碼獲得。是以使用==比較兩個對象結果為false,因為它們并不是一個對象,它們的位址值不同。

例3:

1 public class StringDemo
 2 {
 3     public static void main(String args[])
 4     {
 5         //StringDemo1();
 6         //StringDemo2();
 7         StringDemo3();
 8 
 9     }
10     public static void StringDemo3()
11     {
12         String str1="abcd";
13         String str2=new String("abcd");
14         System.out.println(str1.equals(str2));
15     }
16     public static void StringDemo2()
17     {
18         String str1="abcd";
19         String str2=new String("abcd");
20         System.out.println(str1==str2);
21     }
22     public static void StringDemo1()
23     {
24         String str1="abcd";
25         String str2="abcd";
26         System.out.println(str1==str2);
27     }
28 }      

View Code

該運作結果為true。

分析:先觀察源代碼:

1  public boolean equals(Object anObject) {
 2         if (this == anObject) {
 3             return true;
 4         }
 5         if (anObject instanceof String) {
 6             String anotherString = (String)anObject;
 7             int n = value.length;
 8             if (n == anotherString.value.length) {
 9                 char v1[] = value;
10                 char v2[] = anotherString.value;
11                 int i = 0;
12                 while (n-- != 0) {
13                     if (v1[i] != v2[i])
14                         return false;
15                     i++;
16                 }
17                 return true;
18             }
19         }
20         return false;
21     }      

View Code

String類的equals方法複寫了Object類的方法,是以它所接收的參數對象并不是String類型的,而是Object類型的,檢視該源碼,我們可以發現首先先比較兩個對象的引用是否相同,如果相同,則傳回true;這是合理的,畢竟如果兩個對象的引用都相同,則兩個對象一定是完全相同的。接下來,如果兩個對象的引用不相同,則并不傳回false,而是挨個比較兩個字元串中的字元是否相同,如果比較完成之後完全相同,則傳回true,否則傳回false。我們最後得出結論,那就是該方法在String類中複寫之後比較的是字元串内容是否相同,相同傳回true,不同傳回false。這裡由于兩個字元串内容相同,是以傳回true。

例四:intern()方法。

1 public class StringDemo
 2 {
 3     public static void main(String args[])
 4     {
 5         //StringDemo1();
 6         //StringDemo2();
 7         //StringDemo3();
 8         //StringDemo4();
 9         //StringDemo5();
10         StringDemo6();
11     }
12     public static void StringDemo6()
13     {
14         String str1=new String("abcd");
15         String str2=str1.intern();
16         String str3="abcd";
17         System.out.println(str1==str2);
18         System.out.println(str2==str3);
19     }
20     public static void StringDemo5()
21     {
22         char buf[]={'A','B','C','D','E'};
23         String str=new String(buf);
24         System.out.println(str);
25     }
26     public static void StringDemo4()
27     {
28         byte buf[]={65,66,67,68,69};
29         String str=new String(buf);
30         System.out.println(str);
31     }
32     public static void StringDemo3()
33     {
34         String str1="abcd";
35         String str2=new String("abcd");
36         System.out.println(str1.equals(str2));
37     }
38     public static void StringDemo2()
39     {
40         String str1="abcd";
41         String str2=new String("abcd");
42         System.out.println(str1==str2);
43     }
44     public static void StringDemo1()
45     {
46         String str1="abcd";
47         String str2="abcd";
48         System.out.println(str1==str2);
49     }
50 }      

View Code

輸出結果為兩行:

false

true

分析:當String對象調用intern方法時,JAVA虛拟機就會到字元串常量池中尋找字元串常量并和目前字元串内容進行比較,如果值相同,則傳回該字元串常量池中的常量的引用,否則建立一個新的常量并傳回該常量的引用。執行String str1=new String("abcd");的時候,字元串常量池中已經有了該常量。執行String str2=str1.intern();時,由于已經有了該常量,是以會傳回該常量的引用。同理,Stirng str3="abcd";時也是如此。是以會出現這樣的結果。

3.String類的構造方法。

我們經常使用String str="xxxx";的形式建立字元串對象,貌似String str=new String("xxx");的形式就沒有用了,其實不然,畢竟這種方式存在即合理,很多時候使用前一種方式并不能解決問題,我們還是要使用後一種方式建立字元串,特别是在需要将其它資料類型轉換成字元串類型的時候。

其它資料類型主要包括字元數組和位元組數組。

3.1位元組數組轉換成字元串。

1 public class StringDemo
 2 {
 3     public static void main(String args[])
 4     {
 5         //StringDemo1();
 6         //StringDemo2();
 7         //StringDemo3();
 8         StringDemo4();
 9 
10 
11     }
12     public static void StringDemo4()
13     {
14         byte buf[]={65,66,67,68,69};
15         String str=new String(buf);
16         System.out.println(str);
17     }
18     public static void StringDemo3()
19     {
20         String str1="abcd";
21         String str2=new String("abcd");
22         System.out.println(str1.equals(str2));
23     }
24     public static void StringDemo2()
25     {
26         String str1="abcd";
27         String str2=new String("abcd");
28         System.out.println(str1==str2);
29     }
30     public static void StringDemo1()
31     {
32         String str1="abcd";
33         String str2="abcd";
34         System.out.println(str1==str2);
35     }
36 }      

View Code

運作結果為:ABCDE。

3.2字元數組轉換成字元串。

1 public class StringDemo
 2 {
 3     public static void main(String args[])
 4     {
 5         //StringDemo1();
 6         //StringDemo2();
 7         //StringDemo3();
 8         //StringDemo4();
 9         StringDemo5();
10 
11 
12     }
13     public static void StringDemo5()
14     {
15         char buf[]={'A','B','C','D','E'};
16         String str=new String(buf);
17         System.out.println(str);
18     }
19     public static void StringDemo4()
20     {
21         byte buf[]={65,66,67,68,69};
22         String str=new String(buf);
23         System.out.println(str);
24     }
25     public static void StringDemo3()
26     {
27         String str1="abcd";
28         String str2=new String("abcd");
29         System.out.println(str1.equals(str2));
30     }
31     public static void StringDemo2()
32     {
33         String str1="abcd";
34         String str2=new String("abcd");
35         System.out.println(str1==str2);
36     }
37     public static void StringDemo1()
38     {
39         String str1="abcd";
40         String str2="abcd";
41         System.out.println(str1==str2);
42     }
43 }      

View Code

輸出結果:ABCDE。

3.3其它構造方法。

String(byte[] bytes, int offset, int length);該方法将指定在offset處開始處的length長度範圍内的位元組轉換成字元串。

String(char[] value, int offset, int count);該方法原理和上述相同。

3.4總結。

通過使用String類的構造方法可以實作位元組數組和字元數組向String類對象的轉換。

二、String類功能

1.擷取。

1.1擷取字元串字元的個數,即字元串長度。

int length();

1.2根據位置擷取字元。

char charAt(int index);

1.3根據字元(字元串)擷取在字元串中的位置。

自前向後找:

int indexOf(int ch);

int indexOf(int ch, int fromIndex);

int indexOf(String str);

int indexOf(String str, int fromIndex);

自後向前找:

int lastIndexOf(int ch);

int lastIndexOf(int ch, int fromIndex);

int lastIndexOf(String str);

int lastIndexOf(String str, int fromIndex);

查找的時候,應當注意不要越界,否則抛出異常。

如果沒有查找到,通常傳回-1,可以根據此判斷字元或者字元串是否存在。

1.4 擷取字元串中的一部分字元串。或者稱為字串。

String substring(int beginIndex, int endIndex);

使用方法:subString,傳回String,有兩個參數,一個是beginIndex,一個是endIndex,截取的到是endIndex之前的一個字元。即beginIndex到endIndex-1。

String substring(int beginIndex)

 ;

重載方法有subString ,隻有一個參數,表示從指定的位置開始,一直到字元串結尾。

2.轉換。

2.1将字元串變成幾部分。如果有這個功能将傳回字元串數組。字元串切割。

String[] split(String regex, int limit);

用法舉例:

String s="張三、李四、王五";

String []arr=s.split(",");

如果不是,而是.,則需要特殊處理,因為.是正規表達式中的特殊字元。轉義\\.

切割動作涉及到正規表達式。

2.2将字元串變成字元數組。

Char[] toCharArray();

2.3将字元串變成位元組數組。

Byte[] getBytes(String charsetName);

打碎成最小機關:位元組。

用法舉例:

String s="ab你";

byte []arr=str.getBytes();

輸出的結果卻是:英文字母變成數字輸出,而中文則變成了兩個負數。

中國的gb2312碼最高位都是1,是以都是負數。

2.4字元串中的大小寫轉換。

String toUpperCase();将字元串中的小寫字元轉換成大寫。

String toLowerCase();将字元串中的大寫字元轉換成小寫字元。

2.5将字元串中的内容進行替換。

String replace(char oldChar, char newChar);

String replace(CharSequence target, CharSequence replacement);

CharSequence是String已經實作的接口。

2.6将字元串兩端的空格去掉。

String trim();

2.7将字元串進行連接配接。

String concat(String str);

concat方法和+的作用差不多。

前者顯得更加專業。

2.8value()方法。

此方法為String類的靜态方法,參數為各種基本資料類型,作用是将基本資料類型轉換成字元串。

3.判斷。

3.1兩個字元串内容是否相同?

boolean equals(Object anObject);

boolean equalsIgnoreCase(String anotherString)

//忽略大小寫進行比較,其實就是先轉換成大寫或者小寫再進行比較。

3.2字元串中是否包含某個字元串?

boolean contains(CharSequence s);

其實是用indexOf方法也可以達到相同的目的。

3.3字元串是否以指定字元開頭,是否以指定字元串結尾。

boolean endsWith(String suffix);

boolean startsWith(String prefix);

4.比較方法。

int compareTo(String anotherString);

int compareToIgnoreCase(String str)

 ;

按照字典序比較兩個字元串。

基本資料類型使用的是比較運算符,而對象比較使用的是compareTo方法。

三、StringBuffer類。

StringBuffer類:

就是字元串緩沖區,是用于存儲資料的容器。

數組也是存儲資料的容器,它和StringBuffer的差別是什麼?

1.長度可變

2.可以存儲不同類型的資料進來。

3.最終要轉成字元串才能使用。

4.可以對字元串進行修改。

該類的構造方法中的參數是整數的時候,指定了該緩沖區的初始容量大小;該類的構造方法是字元串時,将會構造一個StringBuffer對象,并将其内容初始化為和該字元串相同。

StringBuffer類的功能:

1.添加。

append方法。參數是基本資料類型,隻有兩種不行:byte和short不行,但是有int可以代替。

初始容量為16個字元。

1 public class StringBufferDemo
 2 {
 3     public static void main(String args[])
 4     {
 5         Demo1();
 6     }
 7     public static void Demo1()
 8     {
 9         StringBuffer sb=new StringBuffer();
10         StringBuffer bs=sb.append(4);
11         System.out.println(sb==bs);
12     }
13 }      

View Code

運作結果為true。

分析:一個容器加入了一些東西以後該容器仍然是該容器,并沒有變化,是以結果為true。

insert方法。該方法參數分為兩部分,一部分是插入的位置,一部分是插入的内容。

1 public class StringBufferDemo
 2 {
 3     public static void main(String args[])
 4     {
 5         //Demo1();
 6         Demo2();
 7     }
 8     public static void Demo2()
 9     {
10         StringBuffer sb=new StringBuffer();
11         sb.append("abba");
12         sb.insert(2,"XXXX");
13         System.out.println(sb);
14     }
15     public static void Demo1()
16     {
17         StringBuffer sb=new StringBuffer();
18         StringBuffer bs=sb.append(4);
19         System.out.println(sb==bs);
20     }
21 }      

View Code

運作結果為:abXXXXba

2.删除。

方法:StringBuffer 

delete(int start, int end);

該方法包含頭不包含尾。

StringBuffer 

deleteCharAt(int index);該方法删除指定位置的字元。

使用該方法可以清空緩沖區:sb.delete(0,sb.length());

清空緩沖區也可以使用sb=new StringBuffer();但是不推薦使用因為會浪費記憶體空間。

3.查找。

和String類幾乎相同。

4.修改。

StringBuffer replace(int start, int end, String str);包含頭不包含尾。該方法的參數個數和String相同,但是位置颠倒了。

void setCharAt(int index, char ch);該方法比較特殊,并沒有傳回StringBuffer對象。該方法将指定位置上的字元替換為指定字元。

void setLength(int newLength);在使用該方法時,如果設定的長度小于内容的長度,則會删除多餘的部分。使用此方法可以達到清空StringBuffer對象的目的,但是不推薦使用。

StringBuffer reverse();反轉字元串

四、StringBuilder類。

此類提供了一個與StringBuffer相容的API。也就是功能用法一模一樣。

這兩個類有什麼不同?

StringBuffer在jdk1.0就出現了,線程安全。

StringBuilder在jdk1.5才出現,線程不安全。

淺析StringBuffer類線程安全的原因:StringBuffer類中有append方法和delete方法,如果一個線程調用append方法,另一個線程同時調用delete方法,在不加同步鎖的情況下,就會出現線程安全性問題。JDK1.0考慮的線程安全性多一點,是以加上了同步;使用同步使得線程更加安全,但是這樣的好處僅僅在多線程程式設計中--如果是單線程,由于不會出現線程安全性問題,是以如果經常使用StringBuffer類的append方法和delete方法,就會極大的降低程式的執行效率,這是每次調用方法都必須判斷鎖造成的。

JDK1.5考慮到了這一點,是以将同步去掉,重新建立了一個類StringBuilder,這是考慮到程式執行效率之後的結果。

我們要知道JDK更新幾乎隻有三點原因:

1.簡化書寫

2.提高效率

3.增加安全性。

而StringBuilder類出現的目的正是為了提高效率,付出的代價就是不安全。

轉載于:https://www.cnblogs.com/kuangdaoyizhimei/p/4006530.html