Upload
r82093403
View
305
Download
0
Embed Size (px)
Citation preview
本投影片(下稱教用資源)僅授權給採用教用資源相關之旗標書籍為教科書之授課老師(下稱老師)專用,老師為教學使用之目的,得摘錄、編輯、重製教用資源(但使用量不得超過各該教用資源內容之 80% )以製作為輔助教學之教學投影片,並於授課時搭配旗標書籍公開播放,但不得為網際網路公開傳輸之遠距教學、網路教學等之使用;除此之外,老師不得再授權予任何第三人使用,並不得將依此授權所製作之教學投影片之相關著作物移作他用。
著作權所有 © 旗標出版股份有限公司
Java 標準類別庫第 17 章
2
學習目標
認識 Java 語言的標準類別庫 學習使用內建的數學運算方法 熟悉基本資料類別 學習 Math 、 Date 、 Calendar 類別的相關應用 學習日期、數值、貨幣的格式化方法 學習搜尋字串與分解字串的技巧
3
前言
前幾章我們開始接觸到 Java 平台提供的各種 『功能』 , 像是執行緒、例外處理、串流類別等。
這些『功能』都是內建在 Java 標準類別庫 (Stand
ard Class Library) 中 , 或是稱為 Java API (Applicat
ion Programming Interfaces, 應用程式介面 ) , 只要在程式中使用這些現成的類別及方法 , 就可進行複雜的工作 , 例如用 BufferedReader 以緩衝方式讀取檔案或鍵盤輸入。
本章將介紹更多實用的 Java API, 方便您撰寫各式各樣的 Java 程式 , 利用程式來解決各式各樣的問題。
4
17-1 甚麼是 Java 標準類別庫?
到目前為止 , 我們已學到的 , 大多屬於『 Java 程式語言』的部份 , 包括變數、運算式、流程控制等基本語法要素 , 以及物件導向的語法:類別、繼承等等。
不過如同第 1 章所介紹的 , Java 語言要發揮功能必須有個可供 Java 程式執行的 Java Platform (Java
平台 ) 環境。 Java Platform 包含兩大部份:
▪ JVM
▪ Java API
5
甚麼是 Java 標準類別庫? JVM 提供一個讓 Java bytecode 程式執行的環境 , 而
Java API 則是一套內含相當多類別、介面定義的集合 , 同版本 Java Platform 所提供的 Java API 種類、數量都相同 , 所以我們可稱之為 Java 標準類別庫 (Standard Class Library) 。
就好像我們可以從大賣場的倉庫中找到許多不同用途的百貨用品、食品 , 我們也能從 Java 標準類別庫這個 Java 程式設計人員專用的倉庫中 , 找到各式各樣的類別來使用 , 讓程式發揮不一樣的功能。
Java 標準類別庫中的類別 , 已依其屬性適當分成多種不同的套件 , 以 JavaSE (Standard Edition) 這個 Java Platform 為例 , 其 Java API 部份提供了如下圖所示的多種套件。
6
甚麼是 Java 標準類別庫?
7
甚麼是 Java 標準類別庫?
每個套件名稱也都暗示了其功能及用途 , 像是前一章介紹的 java.io 套件就是有關輸入與輸出的類別集合;而圖中的 Security 所指的 java.security 套件 , 則是與安全性有關的類別集合。
在眾多的套件中 , 有關圖形使用者介面及繪圖的幾個套件 , 例如上圖有一列包括 AWT 、 Swing 、 Java
2D , 這三項合稱為 Java Foundation Classes (簡稱JFC), 在附錄 A 就會介紹這部份套件的用法。
8
甚麼是 Java 標準類別庫?
如圖示 , Java API 的內容相當多 , 也不是一本入門書可介紹完的 , 因此本書只能做重點式的介紹。前一章我們介紹過 java.io 套件中的輸出入類別和介面 ,
本章則要介紹以下 3 個套件中一些實用的類別:▪ java.lang :顧名思義 , 此套件包含了 Java 語言最基本的核心類別 , 其中包括我們已學過的字串、執行緒、及例外類別 , 都屬於此套件。而本章要介紹的則是可讓我們處理數字的 Math 類別 ,
以及可用來包裝基本資料型別的『基本資料類別』。
9
甚麼是 Java 標準類別庫?
▪ java.util :這個套件有如 Java 程式設計的萬用工具箱 , 提供了開發各種程式都可能會用到的輔助性類別。例如處理日期的 Date 、 Calendar 類別 , 設定國別語系的 Locale 類別 , 搜尋與分解字串的 regex.Patt
ern 、 regex.Matcher 、及 Scanner 類別等。
▪ java.text :提供將資料格式化的類別 , 例如 DateFor
mat 可進行日期的格式化 , 以及 NumberFormat 可進行數值與貨幣的格式化。
10
查看 Java API 文件
當然在整個 Java API 中還有很多功能強大且實用的類別 , 也許您會發現有某個套件對解決您的問題更有幫助。
但限於本書篇幅 , 我們無法一一介紹所有的類別 , 若您想認識一下 Java API 中到底有哪些套件、類別可使用 , 建議直接連上昇陽公司的 Java 線上文件網站 (http://java.sun.com/javase/6/docs/) 一探究竟。
11
查看 Java API 文件
12
查看 Java API 文件
13
查看 Java API 文件
14
查看 Java API 文件
▪ 您也可先在左上框中點選要查閱的套件 , 則左下框即會篩選出該套件中的所有類別 , 以供您點選查閱。
15
17-2 基本資料類別
第 11 章提過 , java.lang 中有一組特別的類別 , 是專用於以物件的方式包裝 Java 基本資料型別 , 所以可稱之為基本資料類別 (Primitive wrapper class)
或包裝類別 (Wrapper class) 。 為什麼要用物件的方式包裝基本型別呢? 因為在某些狀況下 , 您要處理的雖然是整數、浮點數等資料型別 , 但要利用的工具卻只接受物件形式的資料 , 此時就要先將基本資料型別包裝成物件再來進行處理 , 在下 一 章要介紹的 Java Collection 就是這類『工具』的代表性範例。
16
基本資料類別 此外這些類別也提供許多實用的 static 方法 , 讓我們方便進行資料格式的轉換 , 例如我們每次從鍵盤取得輸入的字串 , 就會呼叫這些方法將字串轉換成所需的格式 ( 像是 Integer.parseInt() 方法 ) 。
本節我們先來進一步認識這些包裝類別 , 每個基本資料型別都有其對應的包裝類別 , 如下:
17
基本資料類別
除了 Boolean 、 Character 外 , 其它幾個類別都是 Number 這個抽象類別的子類別。
而且這幾個用來存放數值的類別 , 都有提供一組相似的方法 ( 例如常用的 parseInt() 、 parseDouble()
等 ) 。 基本資料類別有個重要的特性不可不知:包裝成物件的數值或字元等 , 其值是無法改變的。
一方面是這些類別都沒有提供修改物件內含值的方法;再者基本資料類別都是 final 類別 , 所以我們也不能從其衍生可更改數值的新類別。
18
基本資料類別
這樣的設計其實是可以理解的 , 畢竟使用基本資料型別的變數已非常方便 , 平常不需多費一道工夫將它們包裝成物件來用。
以下我們就先來看如何建立包裝類別的物件及取出物件中的資料。
19
17-2-1 建立基本資料類別物件
建構方法 取得物件的值 基本資料類別的常數
20
建構方法
建立基本資料類別的物件 , 相當於將基本型別的變數值裝到物件中。
建立的方法很簡單 , 就是直接以 new 呼叫類別的建構方法 , 例如建立一個 Boolean 物件可用如下的程式:
21
建構方法
關於各類別的建構方法簡單整理如下:▪ Character 類別的建構方法只接受字元型別的參數。
▪ Boolean 、 Byte 、 Double 、 Integer 、 Long 、 Shor
t 類別的建構方法 , 只接受其對應型別的變數、字面常數或字串為參數。例如上述的例子中 , 就用布林變數和字串建立 Boolean 類別的物件。下面是 Short
的範例:
22
建構方法
▪ Float 除了能用 float 型別和字串為建構方法的參數 ,
也能直接用 double 型別的變數當參數呼叫建構方法 ,
不需自行將參數做強制型別轉換。
23
取得物件的值
當我們將基本資料型別包裝成物件後 , 可透過類別所提供的多種方法 , 將其值取出使用。
這些類別至少都提供一種 xxxValue() 方法可傳回物件的值 , 其中 xxx 需代換為基本資料型別的名稱 ,
例如 Boolean 物件可使用 booleanValue() 方法、Character 物件可使用 charValue() 方法。
24
取得物件的值
至於各 Number 類別的子類別就較具彈性 , 它們的物件可呼叫下列傳回數值型別的方法 , 因為這些方法都是繼承自 Number 抽象類別 , 這些方法包括:
25
取得物件的值
使用上列方法時要注意 , 對範圍較大的物件 ( 例如 Double), 取其較小範圍的基本資料型別 (byte), 就可能發生無法表示的情形 , 請參考以下範例程式:
26
取得物件的值
27
取得物件的值
28
取得物件的值
1. 第 7 、 8 行分別建立 Integer 、 Double 類別物件。
2. 第 11 、 14 行分別以基本資料類別的物件為參數 ,
呼叫自訂的 showall() 方法進行示範。3. 第 17〜 25 行自訂的 showall() 方法 , 只是單純呼叫各類別的 xxxValue() 方法並輸出結果。此方法宣告的參數為 Number 類別的物件 , 所以程式中可用 Integer 、 Double 類別的物件為參數呼叫之。
29
取得物件的值
如執行結果所示 , 當物件的數值超出取值方法傳回的基本資料型別所能表示的範圍時 , 經常會出現不可預期的結果。
例如上例中的 123456789 轉成 byte 和 short 時分別變成 21 、 -13035, 而轉成 float 型別時 , 也產生一點誤差變成 1.23456792E8 ( 相當於 123456792) 。
至於倒數第 4 個輸出的 Infinity, 則是 Java 特別定義的常數 , 代表無限大的意思 (因為 5.376543e200
遠超過 float 可表示的範圍 ) , 以下就來認識基本資料類別中所定義的常數值。
30
基本資料類別的常數
除了 Boolean 類別外 , 其它幾個基本資料類別都有定義至少 3 個 static 變數 , 用以表示一些常數值。
其中最普通的一類常數 , 就是表示各基本資料型別的數值範圍 ( 可表示的最大值及最小值 ) , 以及各型別的大小 ( 所佔的位元數 ) 。
各型別的這 3 個常數值如下表所示。
31
基本資料類別的常數
32
基本資料類別的常數
除此之外 , 浮點數的 Float 、 Double 類別 , 分別各有 3 個代表極限值及非數值 (Not-a-Number, NaN)
等特殊值的 static 變數:
33
17-2-2 基本資料類別與字串
認識基本資料類別物件的建立及取值方式後 , 我們再多介紹一些與字串相關的方法。
這些方法大概可分為幾類:▪ 從字串建立類別物件:此類方法和前面介紹的建構方法有點像 , 可將一字串轉成數值型的類別物件。但建構方法的字串只能用十進位表示 , 而以下要介紹的方法不但可接受以不同數字系統表示的字串 , 而且是屬於 static 方法。
▪ 從類別物件產生字串:各資料類別物件都可呼叫特定方法將其值轉成字串表示。
34
基本資料類別與字串
▪ 將基本資料型別轉成字串:這類是各類別提供的 stati
c 方法 , 可用來將各基本資料型別轉成字串表示。
▪ 將字串轉成基本資料型別:同樣是 static 方法 , 而且我們已用過多次 , 每次由鍵盤取得輸入時的用的 Inte
ger.parseInt() 、 Double.parseDouble() 就屬此類。
35
從字串建立類別物件
除了 Character 類別外 , 各基本資料類別至少都提供一個 static 的 valueOf() 方法 , 只要以適當格式的字串呼叫之 , 即可傳回該類別的物件。例如:
36
從字串建立類別物件
整數型類別除了有類似上列的 valueOf() 方法 , 還有個多重定義的版本可指定此字串所採的數字系統:
以上僅列 Integer 類別的 valueOf() 方法 , 其它 B
yte 、 Short 、 Long 也都有這個方法可用 , 但它們的傳回值都是該類別所對應的型別 , 請參考下列程式。
37
從字串建立類別物件
38
從字串建立類別物件
39
從字串建立類別物件
1. 第 7〜 10 行宣告 4 個以不同數字系統表示的數字字串。
2. 第 12〜 15 行分別呼叫各整數型類別的 valueOf
() 方法將字串轉換成數字物件 , 並輸出結果。 使用 valueOf() 方法時要特別注意:如果字串內容
不符合數字格式、或是數字超出物件可表示的範圍 ( 例如在上列程式中將 str16 轉成 Byte 物件 ), 都會引發 NumberFormatException 例外。
40
將類別物件、資料型別轉成字串
在第 11 章已提過所有基本資料類別都有實作各自的 toString() 方法 , 可將物件轉換成字串表示 , 所以我們能在 print() 、 println() 方法中直接將之輸出 ,
或者轉成字串來處理。 除了將物件轉成字串外 , 各數值型的類別也都支援以類別名稱來呼叫 toString() 的方法 , 可將其對應的基本資料型別變數轉換成字串。
41
將類別物件、資料型別轉成字串
但各類別的 toString() 方法都只能將數值轉成 10
進位制的字串表示 , 若想轉成 2 進位、 8 進位、 1
6 進位、甚至於其它數字系統等方式來表示 , 則需使用只有 Integer 、 Long 類別才提供的下列方法:
42
將類別物件、資料型別轉成字串
此處所列為 Integer 類別的方法 , Long 類別也有一組同名的方法 , 只不過它們接受的參數型別為 long 。
以下就是使用這些方法將整數轉成不同進位表示的字串範例:
43
將類別物件、資料型別轉成字串
44
將類別物件、資料型別轉成字串
1. 第 7 、 8 行分別宣告 int 、 long 型別的變數 , 以供程式轉成字串。
2. 第 10〜 13 行分別呼叫各 toXxxString() 方法將字串轉換成數字物件 , 並輸出結果。
45
將字串轉成基本資料型別
基本資料類別也提供多個方法 , 可將字串轉成基本資料型別。
其中有一類方法 , 就是每次從鍵盤取得輸入時 , 用來將字串轉成基本資料型別的 Integer.parseInt() 、 Do
uble.parseDouble() 等方法。 這幾個基本的 parseXxx() 方法我們都已用過多次 ,
就不再多介紹。
46
將字串轉成基本資料型別
比較特別的是 , 整數型的類別所提供的 parseXxx()
方法 , 也有另一種形式 , 可加上待轉換字串是用哪一種數字系統的參數 , 如此就能將不同進位表示的字串轉成基本資料型別:
47
將字串轉成基本資料型別
我們直接來看以下的應用實例:
48
將字串轉成基本資料型別
49
將字串轉成基本資料型別
50
將字串轉成基本資料型別
51
將字串轉成基本資料型別
1.第 12 〜 35 行以迴圈的方式讓程式會一直循環請使用者輸入數字 , 並進行轉換。
2.第 18〜 29 行的 try 段落主要是預防第 19 、 27
行轉換數字時發生格式錯誤的例外。3.第 21 行用 if 判斷使用者是否輸入 0, 是就跳出迴圈 , 結束程式。
4.第 30〜 34 行的 catch 區塊會捕捉 NumberFor
matException 例外 , 並輸出一段訊息。 catch 區塊結束後 , 仍會重新執行迴圈。
52
將字串轉成基本資料型別
Character 類別也有一個類似的方法 , 可將字元轉成數字:
例如 Character.digit('A', 16) 會傳回 10( 在 16 進位中 , A 代表 10 進位的 10) 。
但 digit() 方法並不會在第一個參數超出範圍時拋出例外 , 而是會傳回 -1, 例如 Character.digit('A', 8)
就會傳回 -1 。
53
將字串轉成基本資料型別
另外還有個類似的方法則是:
這個方法是將英文字母接續在數字 0〜 9 後面排列 ( 不分大小寫 ), 例如:
除了英文字母外 , Unicode 中定義的羅馬數字也會傳回代表的數值 , 例如:
54
17-2-3 基本資料類別所提供的其它方法
除了上述各種轉換方法外 , 基本資料類別也提供一些簡單實用的『工具』方法 , 可讓我們對物件的值做其它處理。
55
字元的判斷與轉換方法
前述介紹的多種方法 , Character 類別大多並未提供 ,
不外是因為單一字元與數字 / 字串間的轉換的實用性並不大。
但 Character 類別其實有提供相當多的 static 方法 ,
可做字元的判斷和轉換。
56
字元的判斷與轉換方法 首先介紹一些判斷字元的方法 , 也就是判斷字元是不是屬於某一特別的類別 , 例如:
這些方法的傳回值都是 boolean 型別 , 是該類字元就傳回 "true" 、不是就傳回 "false" 。關於空白字元要說明一下 , 舉凡空白、 '\t' 、 '\n' 等都算是空白字元。
57
字元的判斷與轉換方法
以下是個利用字元方法的簡單範例:
58
字元的判斷與轉換方法
59
字元的判斷與轉換方法
由執行結果可發現:▪ 不論中英文 , 每個字 (母 ) 都視為一個字元。▪ 即使按了多下 [Tab] 鍵產生很寬的空白 , 每個 [Tab] 鍵仍只計為 1 個空白字元 , 所以程式會計算為 "6 個空白字元 " 。
▪ 程式並未計算標點符號 , 所以輸入的標點符號都會被忽略。
60
字元的判斷與轉換方法
至於轉換字元的方法則有下面 2 個:
這 2 個方法都會傳回轉換後的字元 , 如果參數 ch
不是有大小寫分別的字元 , 就傳回原來的字元。因此像下列敘述也不保證會傳回 true :
61
比較的方法
要做基本資料類別物件間的比較 , 若只是看兩者是否相等 , 可使用第 11 章介紹的繼承自 java.lang.Obj
ect 的 equals() 方法。 若要比較誰大誰小的話 , 可使用除了 Boolean 類別以外 , 其它類別都提供的 compareTo() 方法:
62
比較的方法 以上為簡化表示 , 所以將參數型別寫成 "Object" , 實際上各類別的 compareTo() 方法都只能比較同類別的物件。
若參數物件是不同類別 , 則會引發 ClassCastException 例外。▪ 注意 , == 是用來比較是否為同一個物件 , 而 equals() 是用來比較物件的意義 ( 內含值 ) 是否相等 , 請不要混為一談。此外 , 當包裝物件與基本型別資料進行 == 比較時 , 包裝物件會先轉換成基本型別資料 , 因此會針對其內含值做比較 , 而非比較是否為同一物件。
▪ 包裝類別的變數也有可能是 null 參照 , 例如『 Integer i; 』 , 則因 i 未參照到實體 , 所以其值為 null, 而非 0 。SCJP 考題中有時會以此做為陷阱。
63
17-3 Math 類別
在前面幾章 , 我們就曾使用過 java.lang 套件中的 Math 類別所提供的功能 , Math 類別提供了一組方便我們進行各種數學運算的方法。
我們可做如下的比喻: Java 的加減乘除運算子提供了普通計算機的計算功能 , 而 Math 類別則提供了『工程型』計算機的計算功能。
64
Math 類別
Math 類別除了提供多種計算方法外 , 還定義了兩個 static 常數:
因此在程式中可直接用這兩個常數進行相關計算。以下就來分類介紹 Math 類別中的各種方法。
65
17-3-1 比較方法
我們要介紹的第一組 Math 類別的方法是簡單的比較方法。
這些方法會比較兩數字 , 並傳回其中的最大值 (max
() 方法 ) 或最小值 (min() 方法 ) 。 雖然像這樣的運算 , 我們也能用簡單的 if/else 或以比較運算字 (?:) 來做;但在寫程式時 , 使用 Math
提供的方法 , 仍不失為一種簡單而快速的方案。
66
比較方法
這兩個方法各有下列 4 種 , 以用於不同的參數類型:
67
比較方法
其實 Math 類別本身也是用比較運算子 ?: 來設計上列傳回較大值或較小值的方法 , 不過當程式的敘述較為複雜時 , 直接用 Math 類別提供的方法 , 會比我們自己在程式敘述中用 ?: 運算字 , 更容易閱讀及瞭解。
上述方法的用法可參考以下範例。
68
比較方法
69
17-3-2 求絕對值與近似值
除了 min() 、 max() 外 , 另一組 Math 類別提供的簡單方法就是求絕對值與近似值。
這些 static 方法如下所示:
70
求絕對值與近似值
初學程式設計者可能對 ceil() 與 floor() 方法不太熟悉 , 其實它們的意義很簡單: ceil 是天花板的意思 , 所以 ceil() 傳回的是大於或等於參數值的最小整數;而 floor 則是地板 , 所以 floor() 會傳回小於或等於參數值的最大整數。
至於 rint() 、 round() 的計算方式雖然不太相同 , 但多數情況下其計算結果都相同 , 只是傳回值的型態不同。
這幾個方法的應用方式 , 請參見以下範例。
71
求絕對值與近似值
72
求絕對值與近似值
73
求絕對值與近似值
在此要補充說明上述方法的一些特別狀況:▪ 呼叫 Math.ceil() 時的參數值若小於 0 、大於 -1,
則傳回值會是 -0.0 。
▪ 呼叫 Math.round() 時的參數值若小於 Integer.MIN_
VALUE, 則傳回值為 Integer.MIN_VALUE ;若大於 I n teger.MAX_VALUE, 傳回值會是 Integer.MAX_V
ALUE 。
▪ 同理 , 呼叫 Math.round() 時的參數若小於 Long.MI
N_VALUE 或大於 Long.MAX_VALUE, 則分別傳回為 Long.MIN_VALUE 或 Long.MAX_VALUE 。
74
17-3-3 基本數學計算方法
介紹了 Math 類別中一些簡單的方法後 , 接下來要開始介紹進行較複雜運算的方法。
首先來看幾個基本的計算功能:
75
基本數學計算方法
pow() 、 sqr t ( ) 、 cbr t ( ) 方法的用法都很簡單 ,
應不必再加說明。 至於 exp() 、 log() 方法雖然一般人不太會用到 , 但在微積分的領域則是很常看到 , 舉凡數學、物理、金融、財務等各種領域 , 都會看到用到自然對數的計算式 , 在此我們就不深入探討。
以下就是一個使用 pow() 來計算定期存款本利和的範例。
76
基本數學計算方法
77
基本數學計算方法
78
基本數學計算方法
1. 在第 12 〜 18 行分別取得利率、及存款年數。2. 第 24 行用 Math.pow() 方法來計算複利計算時的
本利和。算出來的結果 , 再用前一章介紹的格式化輸出方式 , 以 printf() 方法及 "%.1f" ( 只顯示小數後 1 位 ) 的方式輸出。
79
17-3-4 產生亂數方法
所謂亂數就是一個由電腦隨機產生的數字 , 就像請大家隨便想一個數字寫下來 , 每次想的都可能不同、各數字彼此間也沒什麼關聯性 , 就叫亂數。
在撰寫某些應用程式時就很需要用到亂數方法 , 最普遍的例子就是遊戲程式 , 例如射擊遊戲中的射擊目標每次出現的位置、行動方向都要不同 , 這時就需利用亂數產生器來產生一個隨機數字 , 以決定射擊目標的出現位置、行動方向等性質。
80
產生亂數方法
Math 類別的 random() 方法就是個會傳回『亂數』的方法 , 它會隨機傳回大於等於 0 、小於 1 之間的倍精度浮點數 , 讓程式取得必要的亂數進行相關計算。▪ 其實電腦只是個機器 , 它並不像人真的可以隨便亂想一個數字出來 , 所以 random() 其實是用特定的演算法產生『 不規則』 的數字 , 並非真的亂數 , 因此也稱之為『虛擬』 亂數 (pseudo random number) 。
以下的程式 , 就是用亂數方法來產生隨機樂透號碼的程式 , 由此範例便可瞭解如何利用 random() 來產生亂數。
81
產生亂數方法
82
產生亂數方法
83
產生亂數方法
1. 第 11 、 12 行取得使用者輸入 , 決定要產生的號碼組數。
2. 第 14〜 34 行的迴圈就是在產生指定組數的號碼。3. 第 16〜 18 行建立一個整數陣列 lotto[], 並將 1〜 49 的數字依序填入其中。
84
產生亂數方法
4. 第 21 〜 31 行的 do/while 迴圈進行產生 6 個隨機數字的動作。因為程式可能產生重複的號碼 ,
但這是不允許的 , 所以不確定迴圈會執行幾次 , 故以 do/while 迴圈來執行。
5. 第 22 行呼叫 Math.random() 方法產生 0 至 4
8 間的亂數。
85
產生亂數方法
6. 第 24 〜 30 行的 if/else 是用來判斷產生的數字是否重複。每產生一新亂數時 , 就取出對應的 lotto
[] 陣列元素值 , 並將該元素值設為 0, 下次若又產生同一數字時 , 就會發現該元素值為 0, 因此就會執行第 28 行的 continue 敘述 , 重新執行迴圈產生另一個亂數。
7. 第 29 行每產生一個數字 , 就將 count 加 1, 當 31 行的 while 檢查 count 不小於 6, 表示已產生 6 個數字了 , 就不再執行迴圈。
86
17-4 日期、數字、貨幣的應用與國際化
在程式中經常會使用到日期、時間資料 , 除了取得目前的日期、時間外 , 有時也會換算為星期幾、加減幾天、或減幾個月 . . . 等。
而在輸入或輸出各類日期、數字、貨幣資料時 , 又往往會因不同的國別、語系而有不同的格式。
這些在 Java API 中都有完善的支援 , 底下我們就一一介紹。
87
17-4-1 Date 與 Calendar 類別的應用
java.util.Date 可用來儲存單一的日期與時間 , 而 ja
va.util.Calendar 則像是萬用月曆 , 可進行各種日期設定、轉換、加減等操作。
這二個類別的常用方法如下:
88
Date 與 Calendar 類別的應用
89
Date 與 Calendar 類別的應用
▪ 以上所指的欄位 , 可以是 YEAR 、 MONTH 、 DAY
_OF_MONTH( 日 ) 、 HOUR_OF_DAY( 時 ) 、 MINU
TE 、 SECOND 、 DAY_OF_WEEK(週 ) 等 , 這些都是在 Calendar 中所定義的靜態具名常數。
▪ Calendar 的 set() 也可直接指定年月日等資料 , 包括 set(年 ,月 , 日 ) 、 set(年 ,月 , 日 ,小時 (24), 分 ) 、及 set(年 ,月 , 日 , 時 , 分 ,秒 ), 其中的參數均為 int 。
▪ 代表月份的數值是由 0 開始 , 所以一月是 0, 二月是 1... ;而代表星期的數值 , 則星期日為 1, 星期一為 2..., 以此類推。
90
Date 與 Calendar 類別的應用
請注意 , 由於 Calendar 為抽象類別 , 所以在建立 Calendar 時不可直接用 new 來建構 , 而必須呼叫其靜態方法 Calendar.getInstance(), 來動態建立並傳回一個 Calendar 的子物件。
其原因主要是因為不同語系在處理日期時間時可能會有一些差異 , 因此 Java 會針對這些差異來建立不同的 Calendar 子類別。有關語系的部份我們稍後會介紹。
91
Date 與 Calendar 類別的應用
另外 , 月曆的 add() 和 roll() 都可針對指定欄位 ( 例如月、日、或分 ) 來加減數值 , 而二者的差異是 roll() 不會進位 , 例如將月曆的日期加 12 個月後 ,
使用 add() 時年份會加 1, 而使用 roll() 則年份不變。
底下來看範例。
92
Date 與 Calendar 類別的應用
93
Date 與 Calendar 類別的應用
1.第 6 行在印出 d 時 , 由於需轉為字串 , 因此會自動呼叫其 toString() 方法。
94
Date 與 Calendar 類別的應用
2. 第 11 、 13 行的 DAY_OF_WEEK 、 MONTH 都是 Calendar 的公開靜態常數 , 因此透過物件 (c) 或類別名稱 Calendar 來存取都可以。在讀取星期幾時 , 會傳回代表星期的數值 (星期日為 1, 星期一為 2...), 所以要減 1 才行。但如果是讀取月份 , 例如 c.get(c.MONTH), 則要加 1 (因為一月是 0) 。
3. 第 14 行 getTime() 會傳回 Date 物件 , 並自動呼叫其 toString() 方法將內容轉為字串。
95
Date 的另一種用法
Date 物件中其實是儲存著一個 long 的變數 , 代表距 1970/1/1 凌晨以後多少毫秒 (千分之一秒 ) 的日期 / 時間。因此我們也可以使用以下方法來操作:
▪ 這些方法雖然很少用到 , 但偶而會出現在 SCJP 考題中 , 所以還是稍微了解一下比較好。
96
17-4-2 國際化的 Locale 類別
java.util.Locale 類別可用來建立代表特定國別語系的物件 , 以便搭配稍後會介紹的 java.text.DateFormat 、java.text.NumberFormat 等格式化的類別 , 來輸出 /
輸入特定語系的日期、數值、貨幣等資料。 以下是 Locale 的建構方法:
97
國際化的 Locale 類別
其中的參數 language 為『 ISO 語言碼』 , 例如中文為 "zh" ;而 country 則為『 ISO 國家碼』 , 例如台灣為 "TW" 。
另外 , Locale 中也定義了一組代表國家、語系的靜態常數 , 例如 Locale.TRADITIONAL_CHINESE 代表繁體中文語系 , 而 Locale.TAIWAN 則代表台灣。
若要查詢 Locale 物件所代表的語系或國家 , 則可使用 getDisplayLanguage() 或 getDisplayCountry()
方法。
98
國際化的 Locale 類別
這二個方法也可在參數中指定要使用哪種語言來輸出查詢結果 , 底下是範例:
99
國際化的 Locale 類別
100
17-4-3 格式化日期的 DateFormat 類別
當我們要輸出 ( 入 ) 特定樣式或語系的日期字串時 ,
就可使用 java.text.DateFormat 類別。 DateFormat 也是一個抽象類別 , 同樣要使用靜態方法來建立其子物件:
101
格式化日期的 DateFormat 類別
其中第 2 、 3 個方法的參數也可以省略 , 但須由最後的參數開始往前省略。省略的參數即使用預設值 (SHORT 樣式及系統語系 ) 。
常用的樣式有 SHORT(短 ) 、 MEDIUM( 中 ) 、 LON
G(長 ) 、 FULL(完整 ) 等。 要將日期格式化為字串時 , 可使用 format() 方法;若要解析特定格式的日期字串 , 則可使用 parse(St r
ing s ) 方法 , 但如果格式不對 , 則會丟出 ParseEx
ception 的例外 , 此例外要在程式中捕捉 (catch) 或宣告 (throws) 。
102
格式化日期的 DateFormat 類別
底下來看範例:
103
格式化日期的 DateFormat 類別
104
格式化日期的 DateFormat 類別
請注意 , 我們在第 3 行靜態匯入了 DateFormat
的所有靜態成員 , 因此可在程式中直接使用其靜態的方法及變數 , 而不用加上類別名稱 ( 例如第 8 、 1
1 行 ) 。
105
17-4- 4 格式化數值與貨幣的 NumberFormat 類別 相對於前面介紹的 java.text.DateFormat 類別 , java.
text.NumberFormat 類別則是專門用來輸出 ( 入 )
特定格式的數值與貨幣。 同樣的 , NumberFormat 也是一個抽象類別 , 要使用靜態方法來建立其子物件:
106
格式化數值與貨幣的 NumberFormat 類別
此類別除了提供前面已介紹過的 format() 及 parse
() 方法外 , 常用的還有:讀取、設定最大小數位數的 getMaximumFractionDigits( ) 、 setMaximumFractio
nDigits(int i), 最少小數位數的 getMinimumFraction
Digits() 、 setMinimumFractionDigits(int i), 以及設定只解析整數部份的 setParseIntegerOnly(boolean b)
等方法。 底下是範例。
107
格式化數值與貨幣的 NumberFormat 類別
108
格式化數值與貨幣的 NumberFormat 類別
109
格式化數值與貨幣的 NumberFormat 類別
110
格式化數值與貨幣的 NumberFormat 類別
1. 在第 3 、 4 行靜態匯入了 Locale 及 NumberFo
rmat 的所有靜態成員 , 因此可在程式中直接使用其靜態的方法或變數 ( 例如第 8 、 12 行 ) 。
2. 第 23 行設定 nf 物件只解析整數部份 , 然後在第 25 行解析一個數值字串。不過請注意 , 在執行 pa
rse() 時要處理 ParseException 例外 , 否則會編譯錯誤。
111
17-5 使用 Regex 來搜尋與分解字串
在第 10 章已介紹過規則表示法 (Regular Expressi
on, 簡稱 regex), 並可用在 String 的幾個方法上:
112
使用 Regex 來搜尋與分解字串
以上這些還只是較陽春的功能 , 為了讓我們更方便、更有效率地搜尋或分解文字 , Java 另外提供了 3 個實用的類別:
113
17-5-1 搜尋字串的 Pattern 與 Matcher 類別 如果想用迴圈來一一找出字串中符合 regex 的部份 ,
那麼使用 java.util.regex.Pattern 及 java.util.rege
x.Matcher 來搜尋是最方便而有效率的了。底下就來看範例:
114
搜尋字串的 Pattern 與 Matcher 類別
115
搜尋字串的 Pattern 與 Matcher 類別
1.第 5 行用靜態方法 Pattern.compile() 來編譯 reg
ex ( 第一個命令列參數 ) 並傳回 Patern 物件 , 在第 7 行則用此物件的 matcher() 方法 , 來傳回可搜尋第二個命令列參數的 Matcher 物件。
2.第 9 行呼叫 Matcher 物件的 find() 方法以尋找下一個符合 regex 的子字串 , 該方法會傳回是否找到的布林值。第 10 行的 start() 會傳回找到的位置 (由 0 算起 ), end() 傳回找到字串之後的下一個位置 , 而 group() 則傳回找到的字串內容。
116
搜尋字串的 Pattern 與 Matcher 類別
3. 本例是尋找第一字為數字 (\d), 且第二字為英數字或底線 (\w) 的字串。有一點要注意 , 就是找過的字元就不會再找了 , 例如第二次找到 12 之後 , 接著會由 3 開始找起 ,
而不是由 2 開始找起。
117
regex 中使用量詞的注意事項 在 regex 中若使用 ? 、 * 、 + 等限制次數的量詞 , 預設會找出最長的符合字串 , 例如用前面的程式來搜尋以 b 結尾的任意字串:
程式會找出最長符合的字串 , 而不會找出較短的 "aab" 或 "b" 。如果希望由字串開頭 (由左往右 ) 找出較短字串 , 則可在量詞後面多加一個 ? (即 ?? 、*? 、 +?), 例如:
118
regex 中使用量詞的注意事項
另外 , 在使用 ? 或 * 時 , 0 長度的字串也會被搜尋出來 , 例如:
119
17-5-2 分解字串的類別 Scanner
String 的 split() 只能將字串一次全部分解為陣列 ,
而 java.util.Scanner 類別則提供了更豪華的功能:1. 可用迴圈的方式來逐一分解字串 , 以便做進一步的處
理 , 或隨時中止迴圈。
2. 可由字串中解析指定型別的資料 , 例如 nextInt() 可由字串中取出一個整數資料。
3. 可由檔案、鍵盤、字串等串流來建構 Scanner 物件 ,
並做為解析的來源資料。
120
分解字串的類別 Scanner
Scanner 預設的分隔符號為連續空白 , 但我們也可用 useDelimeter(String pattern) 來指定一個 regex
樣式做為分隔。 每次要讀取下一個片斷 (Token) 時 , 則可使用 nex
t() 方法傳回片斷字串 , 或使用 nextXxx() 方法 (Xx
x 表 Char 以外的基本型別 ) 讀取片斷並轉為指定的型別。
而 hasNext() 及 hasNextXxx() 則可用來判斷是否還有下一個字串 , 或還有可轉為 Xxx 型別的資料片斷。
121
分解字串的類別 Scanner
底下範例以預設的連續空白為分隔 , 分別用解析字串與解析資料型別的方式 , 來解析命令列傳入的參數:
122
分解字串的類別 Scanner
123
分解字串的類別 Scanner
124
17-A 求任意次方根
125
1. Given:
What is the result?
A. short, Long B. Short, Long C. Short, ShortD. Compilation fails. E. An exception is thrown at runtime..
126
127
2. What is the result of following program?
A. int B. short C. Short D. Compilation fails. E. An exception is thrown at runtime.
128
3. Please place the correct Answers to the Output empty boxes.
129
4. What 's the result of following Code?
A. 3B. 3.141593C. %dD. Compilation fails.E. An Exception is thrown at runtime.
130
5. What will be the result if current day is 2009/10/31?
A. 31-Dec-2009 B. Dec 31, 2009 C. 31/12/09D. Compile fails at line 8. E. Compile fails at line 6 and 8.F. An exception is thrown at runtime.
131
6. What is the result? (Choose two.)
A. s1 = 3 B. s1 = 3.142 C. s1 = 3.141593
D. s2 = 5 E. s2 = 5.0 F. s2 = 5.00
132
7. What is the result of following code?
A. 3 B. 8 C. 0
D. Compilation fails. E. An exception is thrown at runtime.
133
7. Given:
Which codes, insert at line 7, will get the default country name and current date?
134
A. A .Locale loc = Locale.getDefault();String s = loc.getDisplayCountry() + f.setFormat(d);
B. B. Locale loc = Locale.getDefault();String s = loc.getDisplayCountry() + f.format(d);
C. C. Locale loc = Locale.getLocale();String s = loc.getDisplayCountry() + f.setFormat(d);
D. D. Locale loc = Locale.getLocale();String s = loc.getDisplayCountry() + f.format(d);