在 Java 程式中經常大量的使用字串,字串在 Java 執行過程中為 java.lang.String 類別的一個實例,String 類別是 Java 標準類別庫眾多類別的其中之一,能夠提供您儲存一連串的字元(陣列)。
其實您經常使用 String 物件,在您撰寫像"Hello!World!"這樣的第一個 Java 程式時,您就使用了 String 物件,因為在 Java 中,以雙引號包括的文字,編譯器會建立 String 物件來表示該文字:
System.out.println("Hello!World!");
如何看出它是個物件,很簡單!即然是物件,就擁有一些可操作的方法,例如 String 物件上有個 toUpperCase()方法,可以將字串中的所有英文字母字元變為大寫字母字元後傳回,所以下面的程式碼片段將顯示"HELLO!WORLD!":
System.out.println("Hello!World!".toUppercase()) ;
每次都使用雙引號來包括文字以得到 String 實例,在撰寫上過於麻煩,您可以使用 String 類別來宣告一個參考名稱,參考至您所建立的 String 實例,例如:
String text = "Hello!World!";
之後直接使用參考名稱來操作所參考的 String 實例,例如:
// 顯示"Hello!World!" System.out.println(text); // 顯示"HELLO!WORLD!" System.out.println(text.toUpperCase());
直接使用雙引號包括所產生的 String 物件,在程式運行期間將一直存在於 String 儲存池中,雙引號包括的字串只要是字元內容相同,都會重複使用 String 儲存池中的同一個 String 物件,您可以使用程式碼 9-1 來作個簡單的驗證。
public class StringDemo{ public static void main(String[] args){ String text1 = "Hello!"; String text2 = "Hello!"; System.out.println("Hello!" == "Hello!"); System.out.println(text1 == "Hello!"); System.out.println(text2 == "Hello!"); System.out.println(text1 == text2); } }程式碼 9-1 StringDemo.java
這邊要提醒一下,當關係運算子"=="使用於兩個物件之比較時,目的是比較兩個物件是否為同一個物件,也就是比較是否存在同一個記憶體位置,在程式運行時,程式碼 9-1 中的"Hello!"只會有一個實例,所以第 6 行到第 9 行的比較,結果都會是 true,如下所示:
使用雙引號包括的文字,是被固定寫在程式碼中的,所以運行時會只存在一個 String 實例並被重複使用,以節省記憶體空間並增進程式執行效率。
圖9-2 程式碼 9-1 中的 text1、text2 參考至同一實例
有很多方法可以建立 String 物件,其中一個方法是使用 new 關鍵字來建立 String 物件並且同時定義字串來初始化物件:
String name = new String("Justin Lin");
上面的程式碼片段將以"Justin Lin"字串的字元內容為基礎,建立一個「新」的 String 物件,注意到這邊說的是「新」的 String 物件,name 所參考的並不是括號中的"Justin Lin" 物件,可以使用程式碼 9-2 來作個簡單的印證。
public class NewString{ public static void main(String[] args){ String name1 = "Justin Lin"; String name2 = new String("Justin Lin"); System.out.println(name1 == "Justin Lin"); System.out.println(name2 == "Justin Lin"); System.out.println(name1 == name2); } }程式碼 9-2 NewString.java
直接在 Java 程式中使用雙引號包括的文字,在運行時會以一個 String 實例存在於 String 儲存池中,而使用 new 建立的 String 實例則是運行時產生,所以兩者不會是同一個實例,程式碼第 4 行是根據"Justin Lin"的字元內容另行建立的String 實例,所以 name1、name2 以==作比較時,結果會是 false。
圖9-3 程式碼 9-2 中的 name1 與 name2 參考至不同實例
程式碼 9-2 的執行結果如下所示:
同樣的,如果您使用 new 分別建立 String 物件,即使它們的字元內容相同,但事實上仍是不同的兩個物件實例,例如以下的程式碼片段將顯示 false 的結果:
String name1 = new String("Justin Lin"); String name2 = new String("Justin Lin"); System.out.println(name1 == name2);
您也可以使用字元陣列為基礎,並使用 new 關鍵字來建立String 實例,例如下面的程式碼片段將建立"Justin"的 String 實例:
char[] array = {'J', 'u', 's', 't', 'i', 'n'}; String name = new String(array);
您也可以指定字元陣列中第幾個字元開始,使用之後的指定字元個數來建立 String 實例,例如下面的程式碼片段從字元陣列的索引 0 開始,擷取 4 個字元來建立 String 實例,結果會顯示"Just":
char[] array = {'J', 'u', 's', 't', 'i', 'n'}; String name = new String(array, 0, 4); System.out.println(name);
重點提示
除了這邊介紹的幾個 String 建構方法之外,還有數個未介紹的 String 建構方式,這些建構的方式是進階議題,建議您參考一下 java.lang.String 的線上 API 文件說明:http://docs.oracle.com/javase/7/docs/api/index.html?java/lang/String.html
String 實例上擁有許多方法可以操作,在這邊先介紹一些簡單的方法操作,像是 String 的大小寫轉換、取得指定的子字串、字元相關操作及字串的搜尋等。
大小寫轉換您可以將 String 實例的英文字母字元內容全部轉為大寫字母或小寫字母,並以新的 String 實例傳回,只要使用toUpperCase()或 toLowerCase()方法即可,例如:
public class StringMethod{ public static void main(String[] args) { String name = "Java"; String upper = name.toUpperCase(); String lower = name.toLowerCase(); System.out.println("原字串:" + name); System.out.println("轉大寫:" + upper); System.out.println("轉小寫:" + lower); } }程式碼 9-3 StringMethod.java
要注意到 toUpperCase()與 toLowerCase()方法以原來的String 物件之字元內容為基礎,傳回一個新的且已轉為大寫或小寫的 String 實例,新的實例與原來的 String 物件是沒有關係,執行結果如圖 9-5 所示:
取得子字串您可以從 String 實例上指定字元開始位置,然後傳回指定的子字串,例如下面的程式片段會顯示"Lin":
System.out.println("Justin Lin".substring(7));
注意字元的位置指定是從 0 開始,您也可以指定字串的起始索引與終止索引,例如下面的程式片段會顯示"Justin":
System.out.println("Justin Lin".substring(0, 6));
使用這個版本的 substring()指定範圍時,傳回的 String 物件將包括起始索引的字元,不包括終止索引的字元。
字元操作字串是由字元所組成,您可以使用 charAt()方法指定索引,以傳回對應的字元,注意索引是從 0 開始,舉個實際的例子,程式碼 9-4 會在每一行顯示字串的內容:
public class CharAtDemo{ public static void main(String[] args){ String name = "Java"; for (int i = 0; i < name.length(); i++){ System.out.println(name.charAt(i)); } } }程式碼 9-4 CharAtDemo.java
String 物件的 length()方法會傳回字串的字元長度,執行結果如下所示:
您也可以使用 String 物件的 toCharArray()方法以字元陣列傳回字串的字元組成,例如程式碼 9-5 以字元陣列顯示的方式來改寫程式碼 9-4。
public class CharDemo{ public static void main(String[] args){ String name = "Java"; char[] array = name.toCharArray(); for (char c : array){ System.out.println(c); } } }程式碼 9-4 CharDemo.java
程式的第 4 行取得字元陣列,並在程式的第 6 行使用 foreach 語法,循序顯示字元陣列的內容,執行結果與程式碼 9-5 是一樣的,可參考圖 9-6 的畫面。
搜尋比對字串的搜尋比對在程式設計中是一個很常遇到的需求,在Java 中您只要操作對應的搜尋方法,就可以完成一些搜尋比對的執行結果,您不用花心思去設計字串搜尋演算法,這是 Java 中操作 String 物件的好處之一。
String 物件上與字串搜尋比對的方法相當的多,表 9-1 先列出一些常用的方法以供參考:
方法名稱 | 說明 |
---|---|
int compareTo(String s) | 依字典順序比較兩個字串的字元內容,傳回 0 表示順序相同,負值表示 String 物件順序在 s 前,正值表示順序在 s 之後 |
boolean contains(CharSequence s) | 測試是否包括實作 CharSequence 介面的物件,例如 String 就實作了CharSequence,簡單的說就是測試字串中是否包括 s |
boolean endsWith(String s) | 測試字串是否以 s 作結束 |
int indexOf(int ch) | 傳回字串中第一個 ch 字元的索引位置 |
int indexOf(String s) | 傳回字串中第一個 s 的起始索引位置 |
int lastIndexOf(int ch) | 傳回字串中最後一個 ch 字元的索引位置 |
int lastIndexOf(String s) | 傳回字串中最後一個 s 的索引位置 |
boolean startsWith(String s) | 測試字串是否以 s 作開始 |
程式碼 9-6 簡單的示範了這些方法的使用與執行結果:
public class MatchDemo{ public static void main(String[] args){ String text = "Java Everywhere"; System.out.println("第一個 a 字元:" + text.indexOf('a')); System.out.println("最後一個 a 字元:" + text.lastIndexOf('a')); System.out.println("第一個 Every:" + text.indexOf("Every")); System.out.println("最後一個 Every:" + text.lastIndexOf("Every")); System.out.println("包括 Java:" + text.contains("Java")); System.out.println("以 Java 為開始:" + text.startsWith("Java")); System.out.println("以 Java 為結束:" + text.endsWith("Java")); } }程式碼 9-6 MatchDemo.java
進行字串內容的比對時,記得是有區分字母大小寫的,程式碼 9-6 執行結果如下所示:
這邊藉由字串內容相等性的比較,來重新複習一個重要的觀念:「關係運算子==用於比較物件時,是用來比較兩個物件是否為同一物件,如果您要比較兩個物件的相等性,請用equals()方法」。
所以如果您要比較兩個 String 物件的字元內容是否相同,您不可以使用"=="來進行比較,而必須使用 equals()方法,以下直接使用程式碼 9-7 來作示範說明。
public class EqualsDemo{ public static void main(String[] args){ String text1 = "Java"; String text2 = new String("Java"); String text3 = new String("Java"); System.out.println( "==比較是否為同一物件.."); System.out.println(text1 == text2); System.out.println(text1 == text3); System.out.println(text2 == text3); System.out.println( "\nequals()比較字元內容.."); System.out.println(text1.equals(text2)); System.out.println(text2.equals(text3)); System.out.println(text1.equals(text3)); } }程式碼 9-7 EqualsDemo.java
對於程式碼 9-7 來說,text1、text2、text3 各參考至不同的物件,所以使用==進行比較時,程式碼第 9、10、11 行都會顯示 false 的結果,在 String 上 equals()被定義為比較字元內容是否相同,text1、text2、text3 的 字元內容都是"Java" ,所以程式碼第 16、17、18 行都會顯示 true 的結果,執行結果如下圖所示:
equals()方法會比較兩個 String 的字元內容是否相同,且區分大小寫,另外還有 equalsIgnoreCase()方法,可以讓您不區分字元的大小寫來進行比較。