java中String類的用法

1、不變模式:java

一個字符串對象建立後它的值不能改變。
String str1="hello";//
建立一個對象hello,不會變;
System.out.println(str1);
str1+=" world!";
//兩個字符串對象粘粘,系統其實建立了一個新的對象,把Str1的指向改了,指向新的對象;hello//變成了垃圾
System.out.println(str1);
//若是一直這樣建立會影響系統的效率;要頻繁的改變字符串對象的值就用StringBuffer來描述;
StringBuffer sb=new StringBuffer("[");
sb.append("hehe");
數組

sb.append("]");//append();不會製造垃圾,真正在改sb的值;
System.out.println(sb);
app

2、對象池jvm

首先要明白,Object obj = new Object();測試

obj是對象的引用,它位於棧中, new Object() 纔是對象,它位於堆中。ui

能夠這樣理解obj是拴在氫氣球上的繩子,new Object() 是氫氣球,咱們經過對象的引用訪問對象,就像咱們那着繩子氫氣球纔不會跑掉。spa

建立一個Stirng對象,主要就有如下兩種方式:.net

java 代碼線程

  1. String str1 = new String("abc");
  2. Stirng str2 = "abc";

雖然兩個語句都是返回一個String對象的引用,可是jvm對二者的處理方式是不同的。對於第一種,jvm會立刻在heap中建立一個String對象,而後將該對象的引用返回給用戶。對於第二種,jvm首先會在內部維護的strings pool中經過String equels 方法查找是對象池中是否存放有該String對象,若是有,則返回已有的String對象給用戶,而不會在heap中從新建立一個新的String對象;若是對象池中沒有該String對象,jvm則在heap中建立新的String對象,將其引用返回給用戶,同時將該引用添加至strings pool中。注意:使用第一種方法建立對象時,jvm是不會主動把該對象放到strings pool裏面的,除非程序調用 Stringintern方法。看下面的例子:設計

java 代碼

  1. String str1 = new String("abc"); //jvm 在堆上建立一個String對象
  2. //jvm strings pool中找不到值爲「abc」的字符串,所以
  3. //在堆上建立一個String對象,並將該對象的引用加入至strings pool
  4. //此時堆上有兩個String對象
  5. Stirng str2 = "abc"; //並無建立對象,由於對象池裏已經有"abc"
  6. if(str1 == str2){
  7. System.out.println("str1 == str2");
  8. }else{
  9. System.out.println("str1 != str2");
  10. }
  11. //打印結果是 str1 != str2,由於它們是堆上兩個不一樣的對象
  12. String str3 = "abc";
  13. //此時,jvm發現strings pool中已有「abc」對象了,由於「abc」equels 「abc」
  14. //所以直接返回str2指向的對象給str3,也就是說str2str3是指向同一個對象的引用
  15. if(str2 == str3){
  16. System.out.println("str2 == str3");
  17. }else{
  18. System.out.println("str2 != str3");
  19. }
  20. //打印結果爲 str2 == str3

3、String / StringBuffer / StringBuilder

String類是字符串常量,是不可更改的常量。而StringBuffer是字符串變量,它的對象是能夠擴充和修改的。

StringBuffer sb=new StringBuffer("[");//建立StringBuffer對象
sb.append("hehe");//
hehe加入字符串,變成 "[hehe"

sb.append("]");//append();不會製造垃圾,真正在改sb的值;
System.out.println(sb);

String str = sb.toString();//"[hehe]",賦值給一個字符串對象str

StringBuilder,一個可變的字符序列。此類提供一個與 StringBuffer 兼容的 API,但不保證同步。該類被設計用做StringBuffer 的一個簡易替換,用在字符串緩衝區被單個線程使用的時候(這種狀況很廣泛)。若是可能,建議優先採用該類,由於在大多數實現中,它比 StringBuffer 要快。

StringBuilder sb=new StringBuilder("[");//建立StringBuilder對象
sb.append("hehe");//
hehe加入字符串,變成 "[hehe"

sb.append("]");//append();不會製造垃圾,真正在改sb的值;
System.out.println(sb);

String str = sb.toString();//"[hehe]",賦值給一個字符串對象str

4、String類中經常使用的方法

String 類包括的方法可用於檢查序列的單個字符、比較字符串、搜索字符串、提取子字符串、建立字符串副本並將全部字符所有轉換爲大寫或小寫。不用去記,用到的時候查API,用的多了天然就熟悉了。

java.lang.String

char charAt (int index)

返回index所指定的字符

String concat(String str)

將兩字符串鏈接

boolean endsWith(String str)

測試字符串是否以str結尾

boolean equals(Object obj)

比較兩對象

char[] getBytes

將字符串轉換成字符數組返回

char[] getBytes(String str)

將指定的字符串轉成制服數組返回

boolean startsWith(String str)

測試字符串是否以str開始

int length()

返回字符串的長度

String replace(char old ,char new)

oldnew替代

char[] toCharArray

將字符串轉換成字符數組

String toLowerCase()

將字符串內的字符改寫成小寫

String toUpperCase()

將字符串內的字符改寫成大寫

String valueOf(Boolean b)

將布爾方法b的內容用字符串表示

String valueOf(char ch)

將字符ch的內容用字符串表示

String valueOf(int index)

將數字index的內容用字符串表示

String valueOf(long l)

將長整數字l的內容用字符串表示

String substring(int1,int2)

取出字符串內第int1位置到int2的字符串

view plaincopy to clipboardprint?

  1. import java.util.Collections;
  2. import java.util.Comparator;
  3. import java.util.LinkedList;
  4. import java.util.List;
  5. public class StringUsage {
  6. // 幾個歐不太用的方法。
  7. public static void main(String[] args) {
  8. // 判斷字符串首/尾。
  9. String contentS = "test String again. test ";
  10. System.out.println(contentS);
  11. System.out.println("contentS.startsWith(\"test\")\t"
  12. + contentS.startsWith("test"));
  13. System.out.println("contentS.endsWith(\"test\")\t"
  14. + contentS.endsWith("test"));
  15. // 忽略大小寫的字符串比較方法。
  16. System.out
  17. .println("contentS.compareToIgnoreCase(contentS.toUpperCase()))\t"
  18. + contentS.compareToIgnoreCase(contentS.toUpperCase()));
  19. // 不區分大小寫的字符串比較。
  20. Comparator<String> cmprStr = String.CASE_INSENSITIVE_ORDER;
  21. List<String> lstStr = new LinkedList<String>();
  22. // 準備數據。
  23. lstStr.add("test");
  24. lstStr.add("Test");
  25. lstStr.add("tEst");
  26. lstStr.add("rest");
  27. lstStr.add("sest");
  28. // 不區分大小寫的排序。
  29. Collections.sort(lstStr, cmprStr);
  30. System.out.println(lstStr);
  31. // 區分大小寫的排序。
  32. Collections.sort(lstStr);
  33. System.out.println(lstStr);
  34. System.out.println("\ntest String.valueOf()");
  35. // valueOf 處理 null 對象的字符串轉換。
  36. try {
  37. String ss = null;
  38. System.out.println(ss);
  39. System.out.println(String.valueOf(null)); // 比較奇怪的地方
  40. } catch (RuntimeException e1) {
  41. e1.printStackTrace();
  42. }
  43. BigDecimal db = null;
  44. try {
  45. System.out.println(((BigDecimal)db).toString());
  46. } catch (Exception e) {
  47. e.printStackTrace();
  48. }
  49. try {
  50. System.out.println(String.valueOf(db));
  51. } catch (Exception e) {
  52. e.printStackTrace();
  53. }
  54. db = new BigDecimal("100.00");
  55. try {
  56. System.out.println(((BigDecimal)db).toString());
  57. } catch (Exception e) {
  58. e.printStackTrace();
  59. }
  60. }
  61. }

5、SCJP題目

String a="Hello World!";
String b="Hello World!";
a=b? a
b是否相等? 爲何?

String a=new String("Hello World!");
String b="Hello World!";
a=b? a
b是否相等 ? 爲何?

解釋:

1. 首先String不屬於8種基本數據類型,String是一個對象。
由於對象的默認值是null,因此String的默認值也是null;但它又是一種特殊的對象,有其它對象沒有的一些特性。

2. new String()
new String(「」)都是申明一個新的空字符串,是空串不是null

3. String str="kvill";

String str=new String (「kvill」);的區別:
在這裏,咱們不談堆,也不談棧,只先簡單引入常量池這個簡單的概念。
常量池(constant pool)指的是在編譯期被肯定,並被保存在已編譯的.class文件中的
一些數據。它包括了關於類、方法、接口等中的常量,也包括字符串常量。
看例1
String s0="kvill";
String s1="kvill";
String s2="kv" + "ill";
System.out.println( s0==s1 );
System.out.println( s0==s2 );
結果爲:
true
true
首先,咱們要知道Java會確保一個字符串常量只有一個拷貝。
由於例子中的s0s1中的」kvill」都是字符串常量,它們在編譯期就被肯定了,因此
s0==s1
true;而」kv」」ill」也都是字符串常量,當一個字符串由多個字符串常量連
接而成時,它本身確定也是字符串常量,因此s2也一樣在編譯期就被解析爲一個字符串常量,因此s2也是常量池中」kvill」的一個引用。因此咱們得出s0==s1==s2;

new String() 建立的字符串不是常量,不能在編譯期就肯定,因此new String()
建立的字符串不放入常量池中,它們有本身的地址空間。

看例2
String s0="kvill";
String s1=new String("kvill");
String s2="kv"+ new String("ill");
System.out.println( s0==s1 );
System.out.println( s0==s2 );
System.out.println( s1==s2 );
結果爲:
false
false
false
2s0仍是常量池中」kvill」的應用,s1由於沒法在編譯期肯定,因此是運行時創
建的新對象」kvill」的引用,s2由於有後半部分new String(「ill」)因此也沒法在編譯
期肯定,因此也是一個新建立對象」kvill」的應用;明白了這些也就知道爲什麼得出此結果了。

4. String.intern()

再補充介紹一點:存在於.class文件中的常量池,在運行期被JVM裝載,而且能夠擴充。Stringintern()方法就是擴充常量池的一個方法;當一個String實例str調用intern()方法時,Java查找常量池中是否有相同Unicode的字符串常量,若是有,則返回其的引用,若是沒有,則在常量池中增長一個Unicode等於str的字符串並返回它的引用;看例3就清楚了。

3
String s0= "kvill";
String s1=new String("kvill");
String s2=new String("kvill");
System.out.println( s0==s1 );
System.out.println( 「**********」 );
s1.intern();
s2=s2.intern(); //
把常量池中"kvill"的引用賦給s2
System.out.println( s0==s1);
System.out.println( s0==s1.intern() );
System.out.println( s0==s2 );
結果爲:
false
**********
false //
雖然執行了s1.intern(),但它的返回值沒有賦給s1
true //
說明s1.intern()返回的是常量池中」kvill」的引用
true


最後我再破除一個錯誤的理解:
有人說,使用String.intern()方法則能夠將一個String類的保存到一個全局Strin
g
表中,若是具備相同值的Unicode字符串已經在這個表中,那麼該方法返回表中已有字符串的地址,若是在表中沒有相同值的字符串,則將本身的地址註冊到表中若是我把他說的這個全局的String表理解爲常量池的話,他的最後一句話,若是在表中沒有相同值的字符串,則將本身的地址註冊到表中是錯的:

看例4
String s1=new String("kvill");
String s2=s1.intern();
System.out.println( s1==s1.intern() );
System.out.println( s1+" "+s2 );
System.out.println( s2==s1.intern() );
結果:
false
kvill kvill
true
在這個類中咱們沒有聲名一個"kvill"常量,因此s1.intern()new String("kvill")是不一樣的,當咱們調用s1.intern()後就在常量池中新添加了一個"kvill"常量,原來的不在常量池中的"kvill"仍然存在,也就不是將本身的地址註冊到常量池中了。
s1==s1.intern()
false說明原來的「kvill」仍然存在;
s2
如今爲常量池中「kvill」的地址,因此有s2==s1.intern()true

5.
關於equals()==:

這個對於String簡單來講就是比較兩字符串的Unicode序列是否至關,若是相等返回true;==是比較兩字符串的地址是否相同,也就是是不是同一個字符串的引用。

6.
關於String是不可變的

這一說又要說不少,你們只要知道String的實例一旦生成就不會再改變了,好比說:
String str=」kv」+」ill」+」 「+」ans」;
就是有4個字符串常量,首先」kv」」ill」生成了」kvill」存在內存中,而後」kvill」又和」 「 生成 」kvill 「存在內存中,最後又和生成了」kvill ans」;並把這個字符串的地址賦給了str,就是由於String不可變產生了不少臨時變量,這也就是爲何建議用StringBuffer的緣由了,由於StringBuffer是可改變的

相關文章
相關標籤/搜索