SlideShare una empresa de Scribd logo
1 de 115
第 10 章

字串 (String)
本投影片(下稱教用資源)僅授權給採用教用資源相關之旗標書籍為教科書之授課老師(下稱老師)專用,老
師為教學使用之目的,得摘錄、編輯、重製教用資源(但使用量不得超過各該教用資源內容之 80% )以製作為
輔助教學之教學投影片,並於授課時搭配旗標書籍公開播放,但不得為網際網路公開傳輸之遠距教學、網路教
學等之使用;除此之外,老師不得再授權予任何第三人使用,並不得將依此授權所製作之教學投影片之相關著
作物移作他用。
著作權所有 © 旗標出版股份有限公司
學習目標
 瞭解 String 類別
 熟練 String 類別所提供的方法
 認識 StringBuffer 與 StringBuilder 類別
 使用規則表示法 (Regular Expression)
前言
 在第 3 章中 , 曾經簡短地介紹過字串這種資料型別 , 而
且在前幾章的範例中幾乎也都使用到字串 , 大家應該對
於字串都不陌生。
 在這一章中 , 我們要針對字串其實是 String 物件這一件
事加以說明 , 並且會介紹 String 類別所提供用來處理字
串內容的許多方法。
 最後 , 還會介紹專責比對字串的規則表示法 (Regular
Expression), 讓大家可以善用字串。
 學會本章介紹的各種 String 類別應用後 , 讀者會發現 ,
不需瞭解 String 類別是如何設計 / 運作 , 我們就能善加
利用它 , 相信讀者也更能體會資訊隱藏的妙用。
10-1 字串的產 生
 字串其實就是 String 物件 , 所以宣告一個字串變數 ,
就等於是宣告一個指到 String 物件的參照 , 然後再
產生 String 物件。
 為了要能正確的產生物件 , 首先來看看 String 類別
所定義常用的建構方法。
字串的產 生
字串的產 生
 其中 StringBuffer 與 StringBuilder 類別會在 10-3
節中介紹。底下就來看看如何透過前 4 個建構方法
產生字串:
字串的產 生
字串的產 生
1. 第 6 行使用不需參數的建構方法建構出來的就是空
的字串 , 也就是一個內 容為 0 個字元的字串。
2. 第 7 行由 test 所指字元陣列建構字串 , 因此建構
出的字串內容為 " 這是個測試字串 " 。
3. 第 8 行由 test 所指字元陣列中索引碼為 3 的元
素開始 , 取出 4 個元素建構字串。由於陣列元素索
引碼是從 0 起算 , 所以建構出來的字串為 " 測試
字串 " 。
字串的產 生
4. 第 9 行由剛剛建立的字串 b 產生副本 , 因此內容
一樣。
5. 第 17 行是特別展示 , 讓大家瞭解雖然字串 d 和
字串 b 的內容一樣 , 但卻是不同的物件個體 , 所以
== 運算比較參照值的結果並不相等。如果要進行
字串內容的比對 , 必須使用稍後會介紹的 equals()
方法。
10-1-1 Java 對於 String 類別的特別支援
 從剛剛的描述可以想見 , 對於像是字串這樣常用的資
料型別 , 如果要一一使用建構方法來建立物件其實並
不方便 , 因此 , Java 語言對於 String 類別提供了幾
個特別的輔助。
使用字面常數建立 String 物件
 Java 對於 String 類別最重要的支援 , 除了可以用
+ 號來連接字串之外 , 還可以使用字面常數來產生
String 物件 , 例如:
使用字面常數建立 String 物件
 其中第 4 行就是直接使用字面常數建立物件。當程
式中有字面常數時 , Java 編譯器其實會產生一個
String 物件來代表所有相同內容的字面常數字串。
 也就是說 , 第 5 行設定給 b 的參照值其實和給 a
的是一樣的 , 都指向同一個 String 物件;而第 6 行
傳給 String 類別建構方法的也是同一個物件。
使用字面常數建立 String 物件
 您可以把這 3 行看成是這樣:

 因此 , 第 8 行的 a == b 就會是 true, 因為 a 和 b
指向同一個物件 , 參照值相等。
 但是 c 則是建立副本 , 指向另一個新物件 , 所以不
論是 a == c 或是 b == c 都不會相同。
 如果要比對字串的內容 , 就必須使用 String 類別的
equals() 方法。
使用字面常數建立 String 物件
使用字面常數建立 String 物件

▪ == 運算子與呼叫 equals() 方法的差異也是應考重點
, 請特別留意。
使用字面常數建立 String 物件
 對於英文字串 , 則有另一個 equalsIgnoreCase() 方
法 , 可在不分大小寫的情況下 , 進行字串比對。
 亦即用 equals() 方法比對時 , "ABC" 和 "abc" 會被
視為不同;但用 equalsIgnoreCase() 方法 , 則會將
"ABC" 和 "abc" 視為相同 , 例如執行
『 "ABC".equalsIgnoreCase("abc") 』會傳回
True 。
10-1-2 String 物件的特性
 String 類別還有幾個特性 , 是單單從表面無法發掘的
, 瞭解這些特性對於正確使用字串有很大的幫助。
自動轉型 (Implicit Conversion)
 搭配連接運算使用時 , 如果連接的運算元中有非
String 物件 , Java 會嘗試將該運算元轉換為 String
物件 , 轉換的方式就是呼叫該運算元的 toString()
方法 , 例如。
自動轉型 (Implicit Conversion)
自動轉型 (Implicit Conversion)
 要注意的是 , toString() 方法必須傳回 String 物件 ,
而且必須加上 public 存取控制。
▪ 若是字串與基本資料型別的變數做連接運算 , 則該變
數會被包裝成對應類別的物件 , 再呼叫該類別的
toString() 方法 , 詳見第 11-4-2 節。
String 物件的內 容無法更改
 String 物件一旦產生之後 , 其內容就無法更改 , 即便
是連接運算 , 都是以運算元連接之後的字串產生新的
String 物件作為運算結果。
 除此之外 , String 類別所提供的各個方法也都是傳回
一個新的字串 , 而不是直接更改字串的內容。
 如果需要能夠更改字串內容的物件 , 必須使用 10-3
節會介紹的 StringBuffer 或是 StringBuilder 類別。
10-2 String 類別的方法
 String 類別提供許多處理字串的方法 , 可以幫助您有
效的使用字串 , 我們將在這一節為您介紹一些重要的
方法 , 相關資訊可以在 JDK 的說明文件中找到。
 要特別再提醒讀者 , 以下傳回值型別為 String 的方
法都是『傳回副本』 , 而不會修改原本的字串內容。
char charAt(int index)
 傳回 int 所指定索引碼的字元 , 字串和陣列一樣 , 索
引碼是從 0 開始算起 , 因此字串中的第 1 個字元的
索引碼就是 0 。
char charAt(int index)
int compareTo(String anotherString)
 以逐字元方式 (Lexically) 與 anotherString 所指字
串的內容比較 , 如果 anotherString 比較大 , 就傳回
一個負數值。
 如果字串內容完全相同 , 就傳回 0 ;如果
anotherString 比較小 , 就傳回一個正數值。
int compareTo(String anotherString)
 至於兩個字串 a 與 b 之間的大小 , 是依照以下的
規則來決定:
1. 由索引 0 開始 , 針對 a 與 b 相同索引碼的字元逐
一比較其標準萬國碼 (Unicode), 一旦遇到相同位置
但字元不同時 , 就以此位置的字元相比較決定 a 與
b 的順序。例如 , a 為 "abcd" 、 b 為 "abed", 索
引碼 0 、 1 這兩個位置的字元皆相同 , 但索引碼 2
的地方 a 為 'c' 、 b 為 'e', 所以 b 比 a 大。
2. 如果 a 與 b 的長度相同 , 且逐一字元比較後 , 同
位置的字元皆相同 , 就傳回 0 。此時 , a.equals(b)
或是 b.equals(a) 皆為 true 。
int compareTo(String anotherString)
3. 如果 a 與 b 長度不同 , 且逐一字元比較後 , 較短
的一方完全和較長的一方前面部分相同 , 就比較 a
與 b 的長度決定大小。例如 , 如果 a 為 "abc" 、 b
為 "abcd", 那麼 a 就小於 b 。
4. 在標準萬國碼中 , 英文字母的順序就是字碼的順序 ,
另外 , 大寫字母是排在小寫字母前面 , 所以相同字母
時 , 小寫大於大寫。
int compareTo(String anotherString)
int compareTo(String anotherString)
 與 equals() 方法類似 , Compareto() 方法也有一個
雙胞胎 compareToIgnoreCase(), 在比較時會將同
一字母大小寫視為相同。
boolean contains(CharSequence s)
 傳回字串中是否包含有 s 所指字串的內容在裡頭。
甚麼是 CharSequence 類別
( 上面方法的參數型別 )
 CharSequence 其實並不是類別 , 而是一個介面
(Interface) 。
 我們會在第 12 章介紹介面 , 這裡您只要知道所有出
現 CharSequence 型別參數的地方 , 都表示該參數
可以是 String 或是 StringBuilder 、 StringBuffer 類
別的物件即可。
boolean endsWith(String suffix)
 傳回是否以指定的字串內容結尾。
void getChars(int srcBegin, int srcEnd,
char[ ] dst, int dstBegin)
 將索引碼 srcBegin 到 srcEnd - 1 的字元 , 複製到
dst 所指字元陣列、由索引碼 dstBegin 開始的元素
中。
區段的表示法
 在 Java 中 , 表示一個區段時 , 都是以開頭元素的索
引碼以及結尾元素的下一個元素的索引碼來表示 , 請
熟悉這種表示方法 , 避免弄錯包含的區段。
int indexOf(int ch)
 傳回 ch 所指定的字元在字串中第一次出現位置的索
引碼 , 如果字串中未包含該字元 , 就傳回 -1 。
int indexOf(int ch)
 這個方法有個雙胞胎的版本 , 叫做 lastIndexOf(),
可以從字串尾端往前尋找。
int indexOf(int ch, int fromIndex)
 indexOf() 方法的多重定義版本 , 可以透過
fromIndex 指定開始尋找的位置。
 只要結合這 2 種 indexOf() 方法 , 就可以逐一找出
字串中所有出現指定字元的位置了。
 這個方法也有個雙胞胎的版本 , 叫做 lastIndexOf(),
可以從字串尾端往前尋找。
int indexOf(String str)
 indexOf() 的多重定義版本 , 尋找的是指定字串出現
的位置。
int indexOf(String str)
 這個方法也有個雙胞胎的版本 , 叫做 lastIndexOf(),
可以從字串尾端往前尋找。
int indexOf(String str, int fromIndex)
 indexOf() 方法的多重定義版本 , 可以透過
fromIndex 指定開始尋找的位置。
 只要結合這 2 種 indexOf() 方法 , 就可以逐一找出
所有出現指定字串的位置了。
 當然也有個對應的 lastIndexOf() 方法 , 可以從字串
尾端往前尋找。
int length()
 傳回字串的長度。
String replace(char oldChar, char newChar)
 將字串中所有出現 oldChar 所指定的字元取代為由
newChar 所指定的字元。
 要提醒您的是 , 這並不會更改原始字串的內容 , 而是
將取代的結果以新的字串傳回。
String replace(CharSequence target,
CharSequence replacement)
 和上一個方法功能類似 , 但是將字串中所有出現
target 所指字串內容的地方都取代為 replacement
所指字串的內容。
boolean startsWith(String prefix)
boolean startsWith(String prefix, int offset)
 startsWith() 的用法和前面看過的 endsWith() 類似 ,
但功能相反 , startsWith() 是用來檢查目前字串是否
是以參數字串 prefix 開頭。
 較特別的是 startsWith() 有兩個參數的版本 , 可指定
從索引位置 offset 開始 , 檢查是否以參數字串
prefix 為開頭。
boolean startsWith(String prefix)
boolean startsWith(String prefix, int offset)
String substring(int beginIndex)
 傳回由 beginIndex 所指定索引開始到結尾的子字串
。
String substring(int beginIndex, int endIndex)
 傳回由 beginIndex 所指定的索引碼開始到
endIndex - 1 所指定的索引碼為止的部分字串。
String toLowerCase()
 傳回將字串中的字元轉成小寫後的副本。
String toUpperCase()
 將字串中的字元全部轉為大寫。
String trim()
 將字串中頭、尾端的空白符號去除,包含空白字元、
定位字元等等。
String trim()

▪ 以上這些方法都經常會用到 , 也是應考的重點。
10-3 StringBuffer 與 StringBuilder 類別
 前 2 節我們一直強調 , String 物件無法更改其字串
內容 , 這主要是因為如此一來 , String 物件就不需要
因為字串內容變長或是變短時 , 必須進行重新配置儲
存空間的動作。
 但如果您必須使用可以隨時更改內容的字串 , 那麼就
必須改用 StringBuffer 或是 StringBuilder 類別。
10-3-1 StringBuffer 類別
 基本上 , 我們可以把 StringBuffer 類別看成是『可
改變內容的 String 類別』。
 因此 StringBuffer 類別提供了各種可改變字串內容
的方法 , 像是可新增內容到字串中的 append() 及
insert() 、可刪除字串內容的 delete() 。
 以下先來看 StringBuffer 類別的建構方法:
StringBuffer 類別
StringBuffer 類別
 還記得在 10-5 頁提過 , Java 會產生一個 String 物
件來代替程式中的字面常數 , 所以第 4 、 5 行也可
直接寫成:
 以下就來介紹 StringBuffer 類別的修改字串方法 ,
這些方法不但會直接修改 StringBuffer 物件的內容 ,
也會將修改後的結果傳回。
append() 方法
 StringBuffer 物件並不能使用 "+" 運算子來連接字串
, 而必須使用 append() 或是 insert() 方法。
 append() 方法會在字串尾端添加資料 , 並且擁有多
重定義的版本 , 可以傳入基本型別、 String 物件以
及其他有定義 toString() 方法的物件。
 它會將傳入的參數轉成字串 , 添加到目前字串的尾端
, 然後傳回自己。
append() 方法
insert() 方法
 insert() 方法和 append() 方法一樣有多種版本 , 但
是它可以透過第 1 個參數 offset 將第 2 個參數插
入到字串中的特定位置。
 offset 代表的是索引碼 , insert() 方法會把資料插入
到 offset 所指的位置之前。
insert() 方法

 在第 11 行可以看到 , 如果第 1 個參數傳入字串的
長度 , 就等於是 append() 了。
StringBuffer delete(int start, int end)
 delete() 方法可以刪除由 start 所指定索引碼開始到
end - 1 所指定索引碼之間的一段字元。
StringBuffer deleteCharAt(int index)
 刪除由 index 所指定索引碼的字元。
StringBuffer replace(int start, int end, String
str)
 將 start 所指定索引碼開始到 end - 1 所指定索引碼
之間的一段字元取代為 str 所指定的字串。
StringBuffer reverse()
 將整個字串的內容頭尾反轉。例如:
void setCharAt(int index, char ch)
 將 index 所指定索引碼的字元取代成 ch 所指定的
字元。
 請特別注意 , 這是唯一一個更改了字串內容 , 但卻沒
有傳回自己的方法 , 在使用時要特別小心。
void setCharAt(int index, char ch)
其他方法
 StringBuffer 也提供下列方法 , 其用法和 String 類
別的同名方法相同 ( 請注意 , 這些方法都不會更改到
物件本身的內容 , 也不會傳回 StringBuffer 物
件) :
▪ char charAt (int index)
▪ void getChars (int srcBegin, int srcEnd, char[ ] dst, int
dstBegin)
▪ int indexOf (String str)
▪ int indexOf (String str, int fromIndex)
其他方法
▪ int lastIndexOf (String str)
▪ int lastIndexOf (String str, int fromIndex)
▪ int length ()
▪ String substring (int start)
▪ String substring (int start, int end)
10-3-2 StringBuilder 類別
 這個類別和 StringBuffer 的用途相同 , 且提供的方
法一模一樣 , 唯一的差別就是此類別並不保證在多執
行緒的環境下可以正常運作 , 有關多執行緒 , 請參考
第
15 章。
 如果您使用字串的場合不會有多個執行緒共同存取同
一字串的話 , 建議可以改用 StringBuilder 類別 , 以
得到較高的效率。
 如果會有多個執行緒共同存取字串的內容 , 就必須改
用 StringBuffer 類別。
10-4 規則表示法 (Regular Expression)
 在字串的使用上 , 有一種用途是接收使用者鍵入的資
料 , 比如說身份證字號、電話號碼、或者是電子郵件
帳號等等。
 為了確保後續的處理正確 , 通常都會希望使用者依據
特定的格式輸入 , 以避免使用者輸入不合乎該項資料
的字元。
 因此 , 在這類應用中 , 一旦取得使用者輸入的資料 ,
第一件事就是要判斷使用者是否依據規定的格式輸入
, 然後才進行後續的處理。
規則表示法 (Regular Expression)
 在 String 類別中 , 雖然已經提供有多個方法可以讓
您比對字串的內容 , 可是要比對字串內容是否符合特
定的格式 , 例如 02-28833498 這種電話號或是
john@yahoo.com.tw 這樣的電子郵件信箱等等具有
規則的樣式 , 使用起來並不方便。
 因此我們需要一種可以描述字串內容規則的方式 , 然
後依據此一規則來驗證字串的內容是否相符。
 String 類別的 matches() 方法 , 就可以搭配規則表
示法來解決這樣的問題。
10-4-1 甚麼是規則表示法
 讓我們先以一個最簡單的範例來說明甚麼是規則表示
法。
 假設程式需要使用者輸入一個整數 , 那麼當取得使用
者輸入的資料後 , 就必須檢查使用者所輸入的是否為
整數。
 要完成這件事 , 最簡單、直覺的方法就是使用一個迴
圈 , 一一取出字串中的各個字元 , 檢查這個字元是否
為數字。
甚麼是規則表示法
甚麼是規則表示法
甚麼是規則表示法
 第 16 行的 for 迴圈就是從 str 所指字串中一一取
出個別字元 , 並比對是否為數字 , 並且在使用者的輸
入資料包含有非數字時顯示錯誤訊息。
比對數字
 由於在標準萬國碼中 , 數字 '0' 、 ' 1' 、 '
2' 、 ..... 、 ' 9' 的字碼是連續的 , 因此只要比對字元
是否位於 '0' 到 '9' 之間 , 即可確認該字元是否為數
字。
甚麼是規則表示法
 如果把第 16 行的迴圈用簡單的一句話來說 , 就是要
檢查使用者所輸入的資料是否都是數字。
 如果改用 String 類別的 matches() 方法搭配規則表
示法 , 就可以更清楚的表達出比對的規則 , 底下就來
修改前面程式的 do 迴圈。
甚麼是規則表示法
甚麼是規則表示法
 第 16 行就是使用 String 類別的 matches() 方法
來檢查字串是否符合某種樣式 , 而 "[0- 9] +" 就是用
來描述字串樣式的規則。 "[0-9]" 是指數字 0 ~ 9 之
間的任意一個字元 , 而後面的 "+" 則是指前面規則
所描述的樣式 ( 此例就是 [0-9]) 出現一次以上 , 所以
整體來說 , 這個規則就是『由一或多個數字所構成的
字串』。
 當字串本身符合所描述的樣式時 , matches() 就傳回
true, 否則傳回 false 。
 因此 , 這個程式就和剛剛使用 for 迴圈檢查的功用一
甚麼是規則表示法
 從這裡您可以看到 , 使用 matches() 方法的好處是
可以專注於要比對的樣式 , 至於如何比對 , 就交給
matches() 方法 , 而不需要自己撰寫程式進行。
 因此 , 如果您需要比對的是這類可以規則化的樣式 ,
建議多多利用 matches() 方法。
10-4-2 規則表示法入門
 為了讓大家可以直接練習 , 所以我們先撰寫了一個測
試的程式 , 可以讓您直接輸入樣式以及要比對的字串
, 並顯示出比對的結果是否相符:
規則表示法入門
規則表示法入門
 這個程式會要求使用者輸入比對的樣式以及字串 , 並
顯示比對結果。
 後續的說明都會以此程式作為測試 , 並顯示執行結果
。
直接比對字串內 容
 最簡單的規則表示法就是直接表示出字串的明確內容
, 比如說如果要比對字串的內容是否為 "print", 那麼
就可以使用 "print" 作為比對的樣式:
限制出現次數
 除了剛剛使用過的 "+" 以外 , 規則表示法中還可以
使用如下常用的次數限制規則 ( 量詞 ) :
限制出現次數
 由於樣式是 "ab?a", 也就是先出現一個 'a', 再出現
最多一個 'b', 再接著一個 'a', 所以 "aa" 或是 "aba"
都相符 , 但是 "abba" 中間出現了 2 個 'b ', 所以不
相符。
字元種類 (Character Classes)
 您也可以用中括號來表示一組字元 , 比如說:

 其中樣式 [bjl] 表示此位置可以出現 'b' 或 'j' 或 'l', 因
此 "a[bjl]a" 這個樣式的意思就是先出現一個 'a', 再出現
一個 'b' 或 'j' 或 'l ', 再接著一個 'a' 。
 在第 2 個執行結果中 , 因為輸入的字串第 2 個字元並非
'b' 或 'j' 或 'l', 所以不相符。
字元種類 (Character Classes)
 您也可以在中括號中使用 "-" 表示一段連續的字碼區
間 , 比如說上一小節使用過的 [0-9] 就包含了數字 ,
而 [a-z] 則包含了小寫的英文字母 , [A-Z] 則包含了
大寫的英文字母 , [a-zA-Z] 就是所有的英文字母了:
字元種類 (Character Classes)
 這個範例的樣式表示先出現一個 ' a ' , 然後接著數字
或是英文字母 , 再接著一個 'a', 所以第 2 個執行結
果因為有 '#' 而不相符。
 另外 , 您也可以在左中括號後面跟著一個 '^' , 排除
中括號中的字元 , 例如:
字元種類 (Character Classes)
 這個樣式表示第 2 個字元不能是小寫英文字母 , 所
以第 1 個執行結果因為第 2 個字元是 'd' 而不相符
。
預先定義的字元種類 (Character Class)
 由於數字或是英文字母
之類的規則很常會用到 ,
因此規則表示法中預先
定義了一些字元種類 ,
如右所示:
▪ 由於句號代表任意字元
, 原來的句號則需以 .
表示。
預先定義的字元種類 (Character Class)

 第 2 個執行結果因為第 2 個字元 'b' 不是數字而不
相符。
群組 (Grouping)
 您也可以使用括號將一段規則組合起來 , 搭配限制次
數使用 , 例如:
群組 (Grouping)
 其中以括號將 "cdc" 組成群組 , 因此整個規則描述
的樣式就是先出現一個 'a', 再出現 2 次 "cdc", 再
出現一個 'a' 。
 第 1 個執行結果中的 "c1c" 以及 "c2c" 都符合
"cdc" 樣式 , 而第 2 個執行結果只有 "c1c" 符合
"cdc" 樣式 , 等於 "cdc" 僅出現 1 次 , 所以比對
不相符。
以字面常數指定樣式
 如果要在程式中以字面常數指定樣式 , 由於 Java 的
編譯器會將 '' 視為跳脫序列的啟始字元 ( 例如 t
表定位字元、 n 表換行字元、  代表  字元 ), 因
此要使用預先定義的字元種類時 , 就必須在前面多加
一個 '', 以便讓 Java 編譯器將 '' 視為一般的字元
, 例如:
以字面常數指定樣式
 如果寫成這樣:
 編譯時就會認為 'd' 是一個不合法的跳脫序列。
10-4-3 replaceAll ( ) 方法
 規則表示法除了可以用來比對字串以外 , 也可以用來
將字串中符合指定樣式的一段文字取代成另外一段文
字 , 讓您可以極富彈性的方式進行字串的取代 , 而不
是僅能使用簡單的 replace() 方法。
 為了簡化 , 我們將剛剛的 RegExTest.java 修改 , 以
方便測試 replaceAll() 方法:
replaceAll ( ) 方法
replaceAll ( ) 方法
 這個程式會要求使者輸入原始的字串、要搜尋的樣式
、以及要將搜尋到的字串片段取代成甚麼內容 , 最後
顯示取代後的結果。
 接下來的內容就以這個程式來測試。
簡單取代
 replaceAll() 最簡單的用法就是當成 replace() 方法
使用 , 以明確的字串內容當成樣式 , 並進行取代:

 因為搜尋的樣式是 "111", 所以取代的結果就是將字
串中的 "111" 取代掉。
使用樣式進行取代
 replaceAll() 最大的用處是可以使用規則表示法 , 例
如:

 這裡搜尋的樣式是 "d+", 所以字串中的 "111" 以及
"34" 都符合這個樣式 , 都會被取代為 " 數字 " 。
使用群組
 有時候我們會希望取代的結果要包含原來被取代的那段
文字 , 這時就可以使用群組的功能 , 例如:

 其中要取代成 " 數字 $1" 中的 "$1" 的意思就是指比對
相符的那段文字中 , 和樣式中第 1 個群組相符的部分。
以本例來說 , 當 "111" 與 "(d+)" 比對相符時 , 第一個
群組就是 "(d+)", 與這個群組相符的就是 "111" 這段文
字 , 所以取代後的結果變成 " 數字 111" ;相同的道理 ,
後面比對出 "34" 時 , 就取代為 " 數字 34" 了。
使用群組
 依此類推 , $2 、 $3 、 ... 自然是指第 2 、 3 、 .... 個
群組了 , 至於 $0 則是指比對出的整段文字 , 例如:

 規則表示法的功能非常強大 , 詳細的說明可以參考
JDK 的說明文件。
10-4-4 split( ) 方法
 split() 方法可依照特定字元來切割字串 , 並將切割的
結果存入字元陣列中傳回。
 例如:『 "Ken,Sue,Tom".split(",") 』就會以逗號來切
割 , 然後傳回 {"Ken","Sue","Tom" } 陣列。
 split() 有二種呼叫方法:
split( ) 方法
 regex 代表一個規則表示法的樣式 , 而 limit 若為正
數 , 則表示最多可切割的元素數目。
 例如 『 "Ken,Sue,Tom".split(",", 2) 』 會傳回只有 2
個元素的 {"Ken","Sue,Tom" } 陣列 , 也就是只會切
割一次。
 若 limit 為負數 , 即表示不限切割的數目。
 若為 0, 則同樣不限切割的數目 , 而且最後面若有空
字串的元素 , 也會自動移除;在呼叫 split() 時若省
略第二個參數 , 則 limit 預設也是 0 。
split( ) 方法
split( ) 方法
 10-A 檢查身份證字號的格式
 10-B 檢核身份證字號
1. Given:

What is the result?
A. x1,y23,z4,

B. x,y,z,

D. x,y,,z,,

E. Compilation fails.

C. x,y,,z,
2. Given :

What is the result?
A. x1,y23,z4,
D. x,y,,z,,

B. x,y,z,
C. x,y,,z,
E. Compilation fails..
3. Given :

Which codes, inserted at line 4, will print "love!"? (Choose
all that apply.)
A. b.delete(0, 2).replace(1,3,"o").append("!");
B. b.substring(2,6).insert(1, "o").replace(2,6,"ve!");
C. b.delete(6,7).delete(0,2).insert(1, "o").replace(2,6,"ve!");
D. b.insert(3, "o").replace(0,2,"").delete(2,4).replace(3,4,"e!");
E. b = "ove".insert(0,1,"l").append("!");
4. What 's the result of following program:

A. unm

B. udm

D. Compilation fails.

E. Runtime error.

C. ude
5. Given:

Which statements are true? (Choose a l l that apply. )
A. This code will have better performance if rewrited to: return
"<"+s.subString(0, n)+">";
B. This code will have better performance if replace StringBuffer
to StringBuilder.
C. If replace StringBuffer to StringBuilder, no other change
should be made.
D. This code is not thread-safe.
E. This code will be thread-unsafe if replace StringBuffer to
StringBuilder.
6. Which statements concerning String, StringBuffer, and
StringBuilder are true? (Choose all that apply.)
A. All three classes have a substring() method.
B. All three classes have a length() method.
C. All three classes have overload append() method.
D. Only String class can use + operator.
E. Only StringBuffer class is thread-safe.
F. StringBuilder has better performance than StringBuffer.
G. The value of an object of those classes can be modified by
their methods

Más contenido relacionado

Similar a SCJP ch10

正则表达式傻瓜式宝典
正则表达式傻瓜式宝典正则表达式傻瓜式宝典
正则表达式傻瓜式宝典yiditushe
 
Java易犯错误
Java易犯错误Java易犯错误
Java易犯错误yiditushe
 
正则表达式入门
正则表达式入门正则表达式入门
正则表达式入门thinkinlamp
 
[圣思园][Java SE]Io 3
[圣思园][Java SE]Io 3[圣思园][Java SE]Io 3
[圣思园][Java SE]Io 3ArBing Xie
 
12, string
12, string12, string
12, stringted-xu
 
3. java basics
3. java basics3. java basics
3. java basicsnetdbncku
 
第3章算法与控制语句
第3章算法与控制语句第3章算法与控制语句
第3章算法与控制语句summerfeng
 
sed -- A programmer's perspective
sed -- A programmer's perspectivesed -- A programmer's perspective
sed -- A programmer's perspectiveLi Ding
 
来自 Google 的 r 语言编码风格指南
来自 Google 的 r 语言编码风格指南来自 Google 的 r 语言编码风格指南
来自 Google 的 r 语言编码风格指南学峰 司
 
07 陣列與字串
07 陣列與字串07 陣列與字串
07 陣列與字串shademoon
 
Swift编程语言入门教程 中文版
Swift编程语言入门教程 中文版Swift编程语言入门教程 中文版
Swift编程语言入门教程 中文版Harvey Zhang
 
Standford 2015 iOS讀書會 week2: 1. Applying MVC 2. More Swift and Foundation Fra...
Standford 2015 iOS讀書會 week2: 1. Applying MVC 2. More Swift and Foundation Fra...Standford 2015 iOS讀書會 week2: 1. Applying MVC 2. More Swift and Foundation Fra...
Standford 2015 iOS讀書會 week2: 1. Applying MVC 2. More Swift and Foundation Fra...彼得潘 Pan
 

Similar a SCJP ch10 (20)

SCJP ch17
SCJP ch17SCJP ch17
SCJP ch17
 
SCJP ch03
SCJP ch03SCJP ch03
SCJP ch03
 
系統程式 -- 第 3 章
系統程式 -- 第 3 章系統程式 -- 第 3 章
系統程式 -- 第 3 章
 
正则表达式傻瓜式宝典
正则表达式傻瓜式宝典正则表达式傻瓜式宝典
正则表达式傻瓜式宝典
 
Java易犯错误
Java易犯错误Java易犯错误
Java易犯错误
 
正则表达式入门
正则表达式入门正则表达式入门
正则表达式入门
 
[圣思园][Java SE]Io 3
[圣思园][Java SE]Io 3[圣思园][Java SE]Io 3
[圣思园][Java SE]Io 3
 
12, string
12, string12, string
12, string
 
学习积累
学习积累学习积累
学习积累
 
SCJP ch16
SCJP ch16SCJP ch16
SCJP ch16
 
3. java basics
3. java basics3. java basics
3. java basics
 
第3章算法与控制语句
第3章算法与控制语句第3章算法与控制语句
第3章算法与控制语句
 
sed -- A programmer's perspective
sed -- A programmer's perspectivesed -- A programmer's perspective
sed -- A programmer's perspective
 
来自 Google 的 r 语言编码风格指南
来自 Google 的 r 语言编码风格指南来自 Google 的 r 语言编码风格指南
来自 Google 的 r 语言编码风格指南
 
第四章 串
第四章 串第四章 串
第四章 串
 
Ch03
Ch03Ch03
Ch03
 
07 陣列與字串
07 陣列與字串07 陣列與字串
07 陣列與字串
 
Scala
ScalaScala
Scala
 
Swift编程语言入门教程 中文版
Swift编程语言入门教程 中文版Swift编程语言入门教程 中文版
Swift编程语言入门教程 中文版
 
Standford 2015 iOS讀書會 week2: 1. Applying MVC 2. More Swift and Foundation Fra...
Standford 2015 iOS讀書會 week2: 1. Applying MVC 2. More Swift and Foundation Fra...Standford 2015 iOS讀書會 week2: 1. Applying MVC 2. More Swift and Foundation Fra...
Standford 2015 iOS讀書會 week2: 1. Applying MVC 2. More Swift and Foundation Fra...
 

Más de r82093403

Ciw going mobile
Ciw going mobileCiw going mobile
Ciw going mobiler82093403
 
The lpic 2 exam prep
The lpic 2 exam prepThe lpic 2 exam prep
The lpic 2 exam prepr82093403
 
Exploration network chapter3
Exploration network chapter3Exploration network chapter3
Exploration network chapter3r82093403
 
Exploration network chapter7
Exploration network chapter7Exploration network chapter7
Exploration network chapter7r82093403
 
Exploration network chapter11
Exploration network chapter11Exploration network chapter11
Exploration network chapter11r82093403
 
Exploration network chapter10
Exploration network chapter10Exploration network chapter10
Exploration network chapter10r82093403
 

Más de r82093403 (20)

Ciw going mobile
Ciw going mobileCiw going mobile
Ciw going mobile
 
The lpic 2 exam prep
The lpic 2 exam prepThe lpic 2 exam prep
The lpic 2 exam prep
 
SCJP ch18
SCJP ch18SCJP ch18
SCJP ch18
 
SCJP ch15
SCJP ch15SCJP ch15
SCJP ch15
 
SCJP ch14
SCJP ch14SCJP ch14
SCJP ch14
 
SCJP ch12
SCJP ch12SCJP ch12
SCJP ch12
 
SCJP ch11
SCJP ch11SCJP ch11
SCJP ch11
 
SCJP ch09
SCJP ch09SCJP ch09
SCJP ch09
 
SCJP ch08
SCJP ch08SCJP ch08
SCJP ch08
 
SCJP ch07
SCJP ch07SCJP ch07
SCJP ch07
 
SCJP ch06
SCJP ch06SCJP ch06
SCJP ch06
 
SCJP ch05
SCJP ch05SCJP ch05
SCJP ch05
 
SCJP ch04
SCJP ch04SCJP ch04
SCJP ch04
 
SCJP ch02
SCJP ch02SCJP ch02
SCJP ch02
 
SCJP ch01
SCJP ch01SCJP ch01
SCJP ch01
 
SCJP ch13
SCJP ch13SCJP ch13
SCJP ch13
 
Exploration network chapter3
Exploration network chapter3Exploration network chapter3
Exploration network chapter3
 
Exploration network chapter7
Exploration network chapter7Exploration network chapter7
Exploration network chapter7
 
Exploration network chapter11
Exploration network chapter11Exploration network chapter11
Exploration network chapter11
 
Exploration network chapter10
Exploration network chapter10Exploration network chapter10
Exploration network chapter10
 

SCJP ch10

  • 1. 第 10 章 字串 (String) 本投影片(下稱教用資源)僅授權給採用教用資源相關之旗標書籍為教科書之授課老師(下稱老師)專用,老 師為教學使用之目的,得摘錄、編輯、重製教用資源(但使用量不得超過各該教用資源內容之 80% )以製作為 輔助教學之教學投影片,並於授課時搭配旗標書籍公開播放,但不得為網際網路公開傳輸之遠距教學、網路教 學等之使用;除此之外,老師不得再授權予任何第三人使用,並不得將依此授權所製作之教學投影片之相關著 作物移作他用。 著作權所有 © 旗標出版股份有限公司
  • 2. 學習目標  瞭解 String 類別  熟練 String 類別所提供的方法  認識 StringBuffer 與 StringBuilder 類別  使用規則表示法 (Regular Expression)
  • 3. 前言  在第 3 章中 , 曾經簡短地介紹過字串這種資料型別 , 而 且在前幾章的範例中幾乎也都使用到字串 , 大家應該對 於字串都不陌生。  在這一章中 , 我們要針對字串其實是 String 物件這一件 事加以說明 , 並且會介紹 String 類別所提供用來處理字 串內容的許多方法。  最後 , 還會介紹專責比對字串的規則表示法 (Regular Expression), 讓大家可以善用字串。  學會本章介紹的各種 String 類別應用後 , 讀者會發現 , 不需瞭解 String 類別是如何設計 / 運作 , 我們就能善加 利用它 , 相信讀者也更能體會資訊隱藏的妙用。
  • 4. 10-1 字串的產 生  字串其實就是 String 物件 , 所以宣告一個字串變數 , 就等於是宣告一個指到 String 物件的參照 , 然後再 產生 String 物件。  為了要能正確的產生物件 , 首先來看看 String 類別 所定義常用的建構方法。
  • 6. 字串的產 生  其中 StringBuffer 與 StringBuilder 類別會在 10-3 節中介紹。底下就來看看如何透過前 4 個建構方法 產生字串:
  • 8. 字串的產 生 1. 第 6 行使用不需參數的建構方法建構出來的就是空 的字串 , 也就是一個內 容為 0 個字元的字串。 2. 第 7 行由 test 所指字元陣列建構字串 , 因此建構 出的字串內容為 " 這是個測試字串 " 。 3. 第 8 行由 test 所指字元陣列中索引碼為 3 的元 素開始 , 取出 4 個元素建構字串。由於陣列元素索 引碼是從 0 起算 , 所以建構出來的字串為 " 測試 字串 " 。
  • 9. 字串的產 生 4. 第 9 行由剛剛建立的字串 b 產生副本 , 因此內容 一樣。 5. 第 17 行是特別展示 , 讓大家瞭解雖然字串 d 和 字串 b 的內容一樣 , 但卻是不同的物件個體 , 所以 == 運算比較參照值的結果並不相等。如果要進行 字串內容的比對 , 必須使用稍後會介紹的 equals() 方法。
  • 10. 10-1-1 Java 對於 String 類別的特別支援  從剛剛的描述可以想見 , 對於像是字串這樣常用的資 料型別 , 如果要一一使用建構方法來建立物件其實並 不方便 , 因此 , Java 語言對於 String 類別提供了幾 個特別的輔助。
  • 11. 使用字面常數建立 String 物件  Java 對於 String 類別最重要的支援 , 除了可以用 + 號來連接字串之外 , 還可以使用字面常數來產生 String 物件 , 例如:
  • 12. 使用字面常數建立 String 物件  其中第 4 行就是直接使用字面常數建立物件。當程 式中有字面常數時 , Java 編譯器其實會產生一個 String 物件來代表所有相同內容的字面常數字串。  也就是說 , 第 5 行設定給 b 的參照值其實和給 a 的是一樣的 , 都指向同一個 String 物件;而第 6 行 傳給 String 類別建構方法的也是同一個物件。
  • 13. 使用字面常數建立 String 物件  您可以把這 3 行看成是這樣:  因此 , 第 8 行的 a == b 就會是 true, 因為 a 和 b 指向同一個物件 , 參照值相等。  但是 c 則是建立副本 , 指向另一個新物件 , 所以不 論是 a == c 或是 b == c 都不會相同。  如果要比對字串的內容 , 就必須使用 String 類別的 equals() 方法。
  • 15. 使用字面常數建立 String 物件 ▪ == 運算子與呼叫 equals() 方法的差異也是應考重點 , 請特別留意。
  • 16. 使用字面常數建立 String 物件  對於英文字串 , 則有另一個 equalsIgnoreCase() 方 法 , 可在不分大小寫的情況下 , 進行字串比對。  亦即用 equals() 方法比對時 , "ABC" 和 "abc" 會被 視為不同;但用 equalsIgnoreCase() 方法 , 則會將 "ABC" 和 "abc" 視為相同 , 例如執行 『 "ABC".equalsIgnoreCase("abc") 』會傳回 True 。
  • 17. 10-1-2 String 物件的特性  String 類別還有幾個特性 , 是單單從表面無法發掘的 , 瞭解這些特性對於正確使用字串有很大的幫助。
  • 18. 自動轉型 (Implicit Conversion)  搭配連接運算使用時 , 如果連接的運算元中有非 String 物件 , Java 會嘗試將該運算元轉換為 String 物件 , 轉換的方式就是呼叫該運算元的 toString() 方法 , 例如。
  • 20. 自動轉型 (Implicit Conversion)  要注意的是 , toString() 方法必須傳回 String 物件 , 而且必須加上 public 存取控制。 ▪ 若是字串與基本資料型別的變數做連接運算 , 則該變 數會被包裝成對應類別的物件 , 再呼叫該類別的 toString() 方法 , 詳見第 11-4-2 節。
  • 21. String 物件的內 容無法更改  String 物件一旦產生之後 , 其內容就無法更改 , 即便 是連接運算 , 都是以運算元連接之後的字串產生新的 String 物件作為運算結果。  除此之外 , String 類別所提供的各個方法也都是傳回 一個新的字串 , 而不是直接更改字串的內容。  如果需要能夠更改字串內容的物件 , 必須使用 10-3 節會介紹的 StringBuffer 或是 StringBuilder 類別。
  • 22. 10-2 String 類別的方法  String 類別提供許多處理字串的方法 , 可以幫助您有 效的使用字串 , 我們將在這一節為您介紹一些重要的 方法 , 相關資訊可以在 JDK 的說明文件中找到。  要特別再提醒讀者 , 以下傳回值型別為 String 的方 法都是『傳回副本』 , 而不會修改原本的字串內容。
  • 23. char charAt(int index)  傳回 int 所指定索引碼的字元 , 字串和陣列一樣 , 索 引碼是從 0 開始算起 , 因此字串中的第 1 個字元的 索引碼就是 0 。
  • 25. int compareTo(String anotherString)  以逐字元方式 (Lexically) 與 anotherString 所指字 串的內容比較 , 如果 anotherString 比較大 , 就傳回 一個負數值。  如果字串內容完全相同 , 就傳回 0 ;如果 anotherString 比較小 , 就傳回一個正數值。
  • 26. int compareTo(String anotherString)  至於兩個字串 a 與 b 之間的大小 , 是依照以下的 規則來決定: 1. 由索引 0 開始 , 針對 a 與 b 相同索引碼的字元逐 一比較其標準萬國碼 (Unicode), 一旦遇到相同位置 但字元不同時 , 就以此位置的字元相比較決定 a 與 b 的順序。例如 , a 為 "abcd" 、 b 為 "abed", 索 引碼 0 、 1 這兩個位置的字元皆相同 , 但索引碼 2 的地方 a 為 'c' 、 b 為 'e', 所以 b 比 a 大。 2. 如果 a 與 b 的長度相同 , 且逐一字元比較後 , 同 位置的字元皆相同 , 就傳回 0 。此時 , a.equals(b) 或是 b.equals(a) 皆為 true 。
  • 27. int compareTo(String anotherString) 3. 如果 a 與 b 長度不同 , 且逐一字元比較後 , 較短 的一方完全和較長的一方前面部分相同 , 就比較 a 與 b 的長度決定大小。例如 , 如果 a 為 "abc" 、 b 為 "abcd", 那麼 a 就小於 b 。 4. 在標準萬國碼中 , 英文字母的順序就是字碼的順序 , 另外 , 大寫字母是排在小寫字母前面 , 所以相同字母 時 , 小寫大於大寫。
  • 29. int compareTo(String anotherString)  與 equals() 方法類似 , Compareto() 方法也有一個 雙胞胎 compareToIgnoreCase(), 在比較時會將同 一字母大小寫視為相同。
  • 30. boolean contains(CharSequence s)  傳回字串中是否包含有 s 所指字串的內容在裡頭。
  • 31. 甚麼是 CharSequence 類別 ( 上面方法的參數型別 )  CharSequence 其實並不是類別 , 而是一個介面 (Interface) 。  我們會在第 12 章介紹介面 , 這裡您只要知道所有出 現 CharSequence 型別參數的地方 , 都表示該參數 可以是 String 或是 StringBuilder 、 StringBuffer 類 別的物件即可。
  • 32. boolean endsWith(String suffix)  傳回是否以指定的字串內容結尾。
  • 33. void getChars(int srcBegin, int srcEnd, char[ ] dst, int dstBegin)  將索引碼 srcBegin 到 srcEnd - 1 的字元 , 複製到 dst 所指字元陣列、由索引碼 dstBegin 開始的元素 中。
  • 34. 區段的表示法  在 Java 中 , 表示一個區段時 , 都是以開頭元素的索 引碼以及結尾元素的下一個元素的索引碼來表示 , 請 熟悉這種表示方法 , 避免弄錯包含的區段。
  • 35. int indexOf(int ch)  傳回 ch 所指定的字元在字串中第一次出現位置的索 引碼 , 如果字串中未包含該字元 , 就傳回 -1 。
  • 36. int indexOf(int ch)  這個方法有個雙胞胎的版本 , 叫做 lastIndexOf(), 可以從字串尾端往前尋找。
  • 37. int indexOf(int ch, int fromIndex)  indexOf() 方法的多重定義版本 , 可以透過 fromIndex 指定開始尋找的位置。  只要結合這 2 種 indexOf() 方法 , 就可以逐一找出 字串中所有出現指定字元的位置了。  這個方法也有個雙胞胎的版本 , 叫做 lastIndexOf(), 可以從字串尾端往前尋找。
  • 38. int indexOf(String str)  indexOf() 的多重定義版本 , 尋找的是指定字串出現 的位置。
  • 39. int indexOf(String str)  這個方法也有個雙胞胎的版本 , 叫做 lastIndexOf(), 可以從字串尾端往前尋找。
  • 40. int indexOf(String str, int fromIndex)  indexOf() 方法的多重定義版本 , 可以透過 fromIndex 指定開始尋找的位置。  只要結合這 2 種 indexOf() 方法 , 就可以逐一找出 所有出現指定字串的位置了。  當然也有個對應的 lastIndexOf() 方法 , 可以從字串 尾端往前尋找。
  • 42. String replace(char oldChar, char newChar)  將字串中所有出現 oldChar 所指定的字元取代為由 newChar 所指定的字元。  要提醒您的是 , 這並不會更改原始字串的內容 , 而是 將取代的結果以新的字串傳回。
  • 43. String replace(CharSequence target, CharSequence replacement)  和上一個方法功能類似 , 但是將字串中所有出現 target 所指字串內容的地方都取代為 replacement 所指字串的內容。
  • 44. boolean startsWith(String prefix) boolean startsWith(String prefix, int offset)  startsWith() 的用法和前面看過的 endsWith() 類似 , 但功能相反 , startsWith() 是用來檢查目前字串是否 是以參數字串 prefix 開頭。  較特別的是 startsWith() 有兩個參數的版本 , 可指定 從索引位置 offset 開始 , 檢查是否以參數字串 prefix 為開頭。
  • 45. boolean startsWith(String prefix) boolean startsWith(String prefix, int offset)
  • 46. String substring(int beginIndex)  傳回由 beginIndex 所指定索引開始到結尾的子字串 。
  • 47. String substring(int beginIndex, int endIndex)  傳回由 beginIndex 所指定的索引碼開始到 endIndex - 1 所指定的索引碼為止的部分字串。
  • 52. 10-3 StringBuffer 與 StringBuilder 類別  前 2 節我們一直強調 , String 物件無法更改其字串 內容 , 這主要是因為如此一來 , String 物件就不需要 因為字串內容變長或是變短時 , 必須進行重新配置儲 存空間的動作。  但如果您必須使用可以隨時更改內容的字串 , 那麼就 必須改用 StringBuffer 或是 StringBuilder 類別。
  • 53. 10-3-1 StringBuffer 類別  基本上 , 我們可以把 StringBuffer 類別看成是『可 改變內容的 String 類別』。  因此 StringBuffer 類別提供了各種可改變字串內容 的方法 , 像是可新增內容到字串中的 append() 及 insert() 、可刪除字串內容的 delete() 。  以下先來看 StringBuffer 類別的建構方法:
  • 55. StringBuffer 類別  還記得在 10-5 頁提過 , Java 會產生一個 String 物 件來代替程式中的字面常數 , 所以第 4 、 5 行也可 直接寫成:  以下就來介紹 StringBuffer 類別的修改字串方法 , 這些方法不但會直接修改 StringBuffer 物件的內容 , 也會將修改後的結果傳回。
  • 56. append() 方法  StringBuffer 物件並不能使用 "+" 運算子來連接字串 , 而必須使用 append() 或是 insert() 方法。  append() 方法會在字串尾端添加資料 , 並且擁有多 重定義的版本 , 可以傳入基本型別、 String 物件以 及其他有定義 toString() 方法的物件。  它會將傳入的參數轉成字串 , 添加到目前字串的尾端 , 然後傳回自己。
  • 58. insert() 方法  insert() 方法和 append() 方法一樣有多種版本 , 但 是它可以透過第 1 個參數 offset 將第 2 個參數插 入到字串中的特定位置。  offset 代表的是索引碼 , insert() 方法會把資料插入 到 offset 所指的位置之前。
  • 59. insert() 方法  在第 11 行可以看到 , 如果第 1 個參數傳入字串的 長度 , 就等於是 append() 了。
  • 60. StringBuffer delete(int start, int end)  delete() 方法可以刪除由 start 所指定索引碼開始到 end - 1 所指定索引碼之間的一段字元。
  • 61. StringBuffer deleteCharAt(int index)  刪除由 index 所指定索引碼的字元。
  • 62. StringBuffer replace(int start, int end, String str)  將 start 所指定索引碼開始到 end - 1 所指定索引碼 之間的一段字元取代為 str 所指定的字串。
  • 64. void setCharAt(int index, char ch)  將 index 所指定索引碼的字元取代成 ch 所指定的 字元。  請特別注意 , 這是唯一一個更改了字串內容 , 但卻沒 有傳回自己的方法 , 在使用時要特別小心。
  • 66. 其他方法  StringBuffer 也提供下列方法 , 其用法和 String 類 別的同名方法相同 ( 請注意 , 這些方法都不會更改到 物件本身的內容 , 也不會傳回 StringBuffer 物 件) : ▪ char charAt (int index) ▪ void getChars (int srcBegin, int srcEnd, char[ ] dst, int dstBegin) ▪ int indexOf (String str) ▪ int indexOf (String str, int fromIndex)
  • 67. 其他方法 ▪ int lastIndexOf (String str) ▪ int lastIndexOf (String str, int fromIndex) ▪ int length () ▪ String substring (int start) ▪ String substring (int start, int end)
  • 68. 10-3-2 StringBuilder 類別  這個類別和 StringBuffer 的用途相同 , 且提供的方 法一模一樣 , 唯一的差別就是此類別並不保證在多執 行緒的環境下可以正常運作 , 有關多執行緒 , 請參考 第 15 章。  如果您使用字串的場合不會有多個執行緒共同存取同 一字串的話 , 建議可以改用 StringBuilder 類別 , 以 得到較高的效率。  如果會有多個執行緒共同存取字串的內容 , 就必須改 用 StringBuffer 類別。
  • 69. 10-4 規則表示法 (Regular Expression)  在字串的使用上 , 有一種用途是接收使用者鍵入的資 料 , 比如說身份證字號、電話號碼、或者是電子郵件 帳號等等。  為了確保後續的處理正確 , 通常都會希望使用者依據 特定的格式輸入 , 以避免使用者輸入不合乎該項資料 的字元。  因此 , 在這類應用中 , 一旦取得使用者輸入的資料 , 第一件事就是要判斷使用者是否依據規定的格式輸入 , 然後才進行後續的處理。
  • 70. 規則表示法 (Regular Expression)  在 String 類別中 , 雖然已經提供有多個方法可以讓 您比對字串的內容 , 可是要比對字串內容是否符合特 定的格式 , 例如 02-28833498 這種電話號或是 john@yahoo.com.tw 這樣的電子郵件信箱等等具有 規則的樣式 , 使用起來並不方便。  因此我們需要一種可以描述字串內容規則的方式 , 然 後依據此一規則來驗證字串的內容是否相符。  String 類別的 matches() 方法 , 就可以搭配規則表 示法來解決這樣的問題。
  • 71. 10-4-1 甚麼是規則表示法  讓我們先以一個最簡單的範例來說明甚麼是規則表示 法。  假設程式需要使用者輸入一個整數 , 那麼當取得使用 者輸入的資料後 , 就必須檢查使用者所輸入的是否為 整數。  要完成這件事 , 最簡單、直覺的方法就是使用一個迴 圈 , 一一取出字串中的各個字元 , 檢查這個字元是否 為數字。
  • 74. 甚麼是規則表示法  第 16 行的 for 迴圈就是從 str 所指字串中一一取 出個別字元 , 並比對是否為數字 , 並且在使用者的輸 入資料包含有非數字時顯示錯誤訊息。
  • 75. 比對數字  由於在標準萬國碼中 , 數字 '0' 、 ' 1' 、 ' 2' 、 ..... 、 ' 9' 的字碼是連續的 , 因此只要比對字元 是否位於 '0' 到 '9' 之間 , 即可確認該字元是否為數 字。
  • 76. 甚麼是規則表示法  如果把第 16 行的迴圈用簡單的一句話來說 , 就是要 檢查使用者所輸入的資料是否都是數字。  如果改用 String 類別的 matches() 方法搭配規則表 示法 , 就可以更清楚的表達出比對的規則 , 底下就來 修改前面程式的 do 迴圈。
  • 78. 甚麼是規則表示法  第 16 行就是使用 String 類別的 matches() 方法 來檢查字串是否符合某種樣式 , 而 "[0- 9] +" 就是用 來描述字串樣式的規則。 "[0-9]" 是指數字 0 ~ 9 之 間的任意一個字元 , 而後面的 "+" 則是指前面規則 所描述的樣式 ( 此例就是 [0-9]) 出現一次以上 , 所以 整體來說 , 這個規則就是『由一或多個數字所構成的 字串』。  當字串本身符合所描述的樣式時 , matches() 就傳回 true, 否則傳回 false 。  因此 , 這個程式就和剛剛使用 for 迴圈檢查的功用一
  • 79. 甚麼是規則表示法  從這裡您可以看到 , 使用 matches() 方法的好處是 可以專注於要比對的樣式 , 至於如何比對 , 就交給 matches() 方法 , 而不需要自己撰寫程式進行。  因此 , 如果您需要比對的是這類可以規則化的樣式 , 建議多多利用 matches() 方法。
  • 80. 10-4-2 規則表示法入門  為了讓大家可以直接練習 , 所以我們先撰寫了一個測 試的程式 , 可以讓您直接輸入樣式以及要比對的字串 , 並顯示出比對的結果是否相符:
  • 82. 規則表示法入門  這個程式會要求使用者輸入比對的樣式以及字串 , 並 顯示比對結果。  後續的說明都會以此程式作為測試 , 並顯示執行結果 。
  • 83. 直接比對字串內 容  最簡單的規則表示法就是直接表示出字串的明確內容 , 比如說如果要比對字串的內容是否為 "print", 那麼 就可以使用 "print" 作為比對的樣式:
  • 84. 限制出現次數  除了剛剛使用過的 "+" 以外 , 規則表示法中還可以 使用如下常用的次數限制規則 ( 量詞 ) :
  • 85. 限制出現次數  由於樣式是 "ab?a", 也就是先出現一個 'a', 再出現 最多一個 'b', 再接著一個 'a', 所以 "aa" 或是 "aba" 都相符 , 但是 "abba" 中間出現了 2 個 'b ', 所以不 相符。
  • 86. 字元種類 (Character Classes)  您也可以用中括號來表示一組字元 , 比如說:  其中樣式 [bjl] 表示此位置可以出現 'b' 或 'j' 或 'l', 因 此 "a[bjl]a" 這個樣式的意思就是先出現一個 'a', 再出現 一個 'b' 或 'j' 或 'l ', 再接著一個 'a' 。  在第 2 個執行結果中 , 因為輸入的字串第 2 個字元並非 'b' 或 'j' 或 'l', 所以不相符。
  • 87. 字元種類 (Character Classes)  您也可以在中括號中使用 "-" 表示一段連續的字碼區 間 , 比如說上一小節使用過的 [0-9] 就包含了數字 , 而 [a-z] 則包含了小寫的英文字母 , [A-Z] 則包含了 大寫的英文字母 , [a-zA-Z] 就是所有的英文字母了:
  • 88. 字元種類 (Character Classes)  這個範例的樣式表示先出現一個 ' a ' , 然後接著數字 或是英文字母 , 再接著一個 'a', 所以第 2 個執行結 果因為有 '#' 而不相符。  另外 , 您也可以在左中括號後面跟著一個 '^' , 排除 中括號中的字元 , 例如:
  • 89. 字元種類 (Character Classes)  這個樣式表示第 2 個字元不能是小寫英文字母 , 所 以第 1 個執行結果因為第 2 個字元是 'd' 而不相符 。
  • 90. 預先定義的字元種類 (Character Class)  由於數字或是英文字母 之類的規則很常會用到 , 因此規則表示法中預先 定義了一些字元種類 , 如右所示: ▪ 由於句號代表任意字元 , 原來的句號則需以 . 表示。
  • 91. 預先定義的字元種類 (Character Class)  第 2 個執行結果因為第 2 個字元 'b' 不是數字而不 相符。
  • 93. 群組 (Grouping)  其中以括號將 "cdc" 組成群組 , 因此整個規則描述 的樣式就是先出現一個 'a', 再出現 2 次 "cdc", 再 出現一個 'a' 。  第 1 個執行結果中的 "c1c" 以及 "c2c" 都符合 "cdc" 樣式 , 而第 2 個執行結果只有 "c1c" 符合 "cdc" 樣式 , 等於 "cdc" 僅出現 1 次 , 所以比對 不相符。
  • 94. 以字面常數指定樣式  如果要在程式中以字面常數指定樣式 , 由於 Java 的 編譯器會將 '' 視為跳脫序列的啟始字元 ( 例如 t 表定位字元、 n 表換行字元、 代表 字元 ), 因 此要使用預先定義的字元種類時 , 就必須在前面多加 一個 '', 以便讓 Java 編譯器將 '' 視為一般的字元 , 例如:
  • 96. 10-4-3 replaceAll ( ) 方法  規則表示法除了可以用來比對字串以外 , 也可以用來 將字串中符合指定樣式的一段文字取代成另外一段文 字 , 讓您可以極富彈性的方式進行字串的取代 , 而不 是僅能使用簡單的 replace() 方法。  為了簡化 , 我們將剛剛的 RegExTest.java 修改 , 以 方便測試 replaceAll() 方法:
  • 97. replaceAll ( ) 方法
  • 98. replaceAll ( ) 方法  這個程式會要求使者輸入原始的字串、要搜尋的樣式 、以及要將搜尋到的字串片段取代成甚麼內容 , 最後 顯示取代後的結果。  接下來的內容就以這個程式來測試。
  • 99. 簡單取代  replaceAll() 最簡單的用法就是當成 replace() 方法 使用 , 以明確的字串內容當成樣式 , 並進行取代:  因為搜尋的樣式是 "111", 所以取代的結果就是將字 串中的 "111" 取代掉。
  • 100. 使用樣式進行取代  replaceAll() 最大的用處是可以使用規則表示法 , 例 如:  這裡搜尋的樣式是 "d+", 所以字串中的 "111" 以及 "34" 都符合這個樣式 , 都會被取代為 " 數字 " 。
  • 101. 使用群組  有時候我們會希望取代的結果要包含原來被取代的那段 文字 , 這時就可以使用群組的功能 , 例如:  其中要取代成 " 數字 $1" 中的 "$1" 的意思就是指比對 相符的那段文字中 , 和樣式中第 1 個群組相符的部分。 以本例來說 , 當 "111" 與 "(d+)" 比對相符時 , 第一個 群組就是 "(d+)", 與這個群組相符的就是 "111" 這段文 字 , 所以取代後的結果變成 " 數字 111" ;相同的道理 , 後面比對出 "34" 時 , 就取代為 " 數字 34" 了。
  • 102. 使用群組  依此類推 , $2 、 $3 、 ... 自然是指第 2 、 3 、 .... 個 群組了 , 至於 $0 則是指比對出的整段文字 , 例如:  規則表示法的功能非常強大 , 詳細的說明可以參考 JDK 的說明文件。
  • 103. 10-4-4 split( ) 方法  split() 方法可依照特定字元來切割字串 , 並將切割的 結果存入字元陣列中傳回。  例如:『 "Ken,Sue,Tom".split(",") 』就會以逗號來切 割 , 然後傳回 {"Ken","Sue","Tom" } 陣列。  split() 有二種呼叫方法:
  • 104. split( ) 方法  regex 代表一個規則表示法的樣式 , 而 limit 若為正 數 , 則表示最多可切割的元素數目。  例如 『 "Ken,Sue,Tom".split(",", 2) 』 會傳回只有 2 個元素的 {"Ken","Sue,Tom" } 陣列 , 也就是只會切 割一次。  若 limit 為負數 , 即表示不限切割的數目。  若為 0, 則同樣不限切割的數目 , 而且最後面若有空 字串的元素 , 也會自動移除;在呼叫 split() 時若省 略第二個參數 , 則 limit 預設也是 0 。
  • 107.  10-A 檢查身份證字號的格式  10-B 檢核身份證字號
  • 108. 1. Given: What is the result? A. x1,y23,z4, B. x,y,z, D. x,y,,z,, E. Compilation fails. C. x,y,,z,
  • 109. 2. Given : What is the result? A. x1,y23,z4, D. x,y,,z,, B. x,y,z, C. x,y,,z, E. Compilation fails..
  • 110. 3. Given : Which codes, inserted at line 4, will print "love!"? (Choose all that apply.) A. b.delete(0, 2).replace(1,3,"o").append("!"); B. b.substring(2,6).insert(1, "o").replace(2,6,"ve!"); C. b.delete(6,7).delete(0,2).insert(1, "o").replace(2,6,"ve!"); D. b.insert(3, "o").replace(0,2,"").delete(2,4).replace(3,4,"e!"); E. b = "ove".insert(0,1,"l").append("!");
  • 111.
  • 112. 4. What 's the result of following program: A. unm B. udm D. Compilation fails. E. Runtime error. C. ude
  • 113. 5. Given: Which statements are true? (Choose a l l that apply. ) A. This code will have better performance if rewrited to: return "<"+s.subString(0, n)+">"; B. This code will have better performance if replace StringBuffer to StringBuilder. C. If replace StringBuffer to StringBuilder, no other change should be made. D. This code is not thread-safe. E. This code will be thread-unsafe if replace StringBuffer to StringBuilder.
  • 114.
  • 115. 6. Which statements concerning String, StringBuffer, and StringBuilder are true? (Choose all that apply.) A. All three classes have a substring() method. B. All three classes have a length() method. C. All three classes have overload append() method. D. Only String class can use + operator. E. Only StringBuffer class is thread-safe. F. StringBuilder has better performance than StringBuffer. G. The value of an object of those classes can be modified by their methods