java 5.0 的新功能. 內 容 大 綱 (1) 泛型 自動裝箱與拆箱 增強的 for 迴圈敘述 c...

51
Java 5.0 的的的的

Post on 21-Dec-2015

256 views

Category:

Documents


0 download

TRANSCRIPT

Java 5.0 的新功能

內 容 大 綱 (1)

泛型 自動裝箱與拆箱 增強的 for 迴圈敘述 C 風格的輸出 格式化的輸入 列舉

內 容 大 綱 (2)

靜態引入 可變數目參數

泛型 (1/5) Java5.0 的新特性之一是引入了泛型 (generics) 的觀

念,在 Java 5.0 中,許多 java.util 類別庫中實作Collection 介面的集聚類別,被改為泛型類別,如Vector 、 ArrayList 、 LinkedList 、 Hashtable 、HashMap 、 Stack 、 Queue 、 PriorityQueue 、Dictionary 、 TreeMap 及 TreeSet 等。

在 Java 5.0 之前我們使用 ArrayList 清單 = new ArrayList(); 來宣告一個屬於 ArrayList 集聚類別的物件 ( 以下簡稱聚集物件 ) ,而所有加入 ArrayList的物件,都是屬於 Object 類別的物件。

泛型 (2/5) 而在物件取出時則必須以轉型 (casting) 的方式

才可正確使用,而這使得型別檢查 (type checking) 無法在編譯時期進行,必須等到執行時期才可以進行 ( 此時若出現錯誤,則會引發例外 ) 。

我們可以使用如 ArrayList<String> 清單 = new ArrayList<String>(); 來宣告一個屬於ArrayList 類別的聚集物件,其中的 < > 符號是借用自 C++ 語言中 Standard Template Library (STL) 中的用法。

泛型 (3/5) 在上例中我們在 < > 中填入 String 類別,這很

明確的表示我們要加入的物件是屬於 String 類別的。如此,可以方便編譯器在編譯時期即進行型別檢查,此時若有錯誤發生,則在編譯時期就可以加以修正。

另外,我們在取用加入的物件時不需要再經過轉型的動作,這使得程式設計方便了許多。

泛型 (4/5) 以下的範例程式中示範了泛型的使用:

泛型 (5/5)

程式執行結果

自動裝箱與拆箱 (1/2) 在 Java 語言聚集物件中 ( 如範例程式附 5-1 中屬

於 ArrayList 類別的物件清單 1 及清單 2) ,只能夠將參考型別資料 ( 也就是物件 ) 加入其中。

要將基本型別資料放入到聚集物件中,就要將該資料以包裝類別 (wrapper, 如 Float 類別 ) 包裝成物件之後才能加入,這個動作稱為 boxing 。

讀者在編寫程式時可以略去裝箱與拆箱的程式片段,這不但可以縮減程式碼的長度並且可以加快程式碼的開發。

自動裝箱與拆箱 (2/2) 以下的範例程式搭配泛型的使用展示自動裝箱與

拆箱的功能。

程式執行結果

增強的 for 迴圈敘述 (1/5) 在 Java 5.0 中新增了 for-each/in 迴圈敘述,

其語法如下所述:for ( 變數宣告 : 陣列或 Iterable 物件 ) 敘述區塊 若我們將上述語法中的 for 關鍵字讀為 for

each ,將冒號 (:) 讀為 in ,則有助於了解上述語法的涵義。

增強的 for 迴圈敘述 (2/5) 我們使用以下的程式片段來說 for-each/in 迴圈敘述

的用法:int[] 陣列

1={31,29,31,30,31,30,31,31,30,31,30,31};String[] 陣列 2= {" 星期一 "," 星期二 "," 星期

三 "," 星期四 "," 星期五 "," 星期六 "," 星期天 "};for (int i: 陣列 1) System.out.print(i+" ");for (String s: 陣列 2) System.out.print(s+" ");

增強的 for 迴圈敘述 (3/5) 上述的程式片段的第一個 for 迴圈的意思為對每

一個在陣列 1 中的整數元素 i 執行System.out.println(i+“ ”) 敘述;而第二個for 迴圈的意思為對每一個在陣列 2 中的 String物件元素 s 執行 System.out.println(s+“ ”)敘述。

其執行結果應為:31 29 31 30 31 30 31 31 30 31 30 31 星期

一 星期二 星期三 星期四 星期五 星期六 星期天

增強的 for 迴圈敘述 (4/5) 我們接著再使用以下的範例程式來說明 for-

each/in 迴圈與 Iterable 物件的配合使用。

增強的 for 迴圈敘述 (5/5)

程式執行結果

C 風格的輸出 (1/6) Java 5.0 在 java.util.Formatter 類別中開始

支援 C 風格的輸出,除了使用屬於 Formatter類別的物件配合 System.out.println() 方法輸出之外,還可以直接使用類似 C 語言 printf 函數的 System.out.printf() 方法。

System.out.printf(” 控制字串” , 運算式 1, 運算式 2, ...);

控制字串中可以包含許多以百分比符號 (%) 引導的控制符號,如下所列:

C 風格的輸出 (2/6)控制符號 含 意%% 在字串中顯示%

%d 以 10 進位整數方式輸出%f 將浮點數以 10 進位方式輸出%e, %E 將浮點數以 10 進位科學記號方式輸出%a, %A 使用科學記號輸出浮點數,以 16進位輸出整數部份,以 10 進位輸出指數部份

%o 以 8 進位整數方式輸出%x, %X 將浮點數以 16 進位方式輸出%s, %S 輸出格式化字串%c, %C 以字元方式輸出%b, %B 輸出布林值 "true" 或 "false"(使用%B則輸出 "TRUE" 或 "FALSE")。另外,非 null值

輸出是 "true" , null值輸出是 "false"

%n 輸出平台相依的換行字元,如果是在Windows 作業系統下實際上會置換為 '/r/n',如果是在 Unix作業系統下則會置換為 '/n'

C 風格的輸出 (3/6) 在上表中的大部份控制字元前,還可以加上如下所列的旗號 (flag) :

特殊旗號 含 意數字 (d格式等 ) 數字代表輸出的欄位總寬度數字 1.數字 2

(f格式等 )數字 1代表輸出的欄位總寬度;數字 2代表輸出的小入部份欄位寬度

+ 正數前輸出 +,負數前輸出 -

空白 正數前輸出空白,負數前輸出 -

0 數字前輸出前導 0

- 輸出向左對齊( 負數以加括號方式輸出, 數字每隔 3位加一逗點# (f 格式 ) 永遠加上小數點# (x 格式 ) 輸出加上 0x字首# (o 格式 ) 輸出加上 0 字首

C 風格的輸出 (4/6) 我們使用以下的程式片段來說明 System.out.printf()

用法:System.out.printf("%d %(d %+d %05d\n", 3, -3,

3, 3);System.out.printf("%.4f", 123.1234567); System.out.printf("%16.2e", 123.1234567);System.out.printf("% ,.2f\n% ,.2f\n",

1234567.123, -1234567.123);System.out.printf("|%f|%n|%12f|%n|

%012f|",10.12345, 10.12345, 10.12345);System.out.printf("%8s","C 風格的輸出功能強大 ");

C 風格的輸出 (5/6) 上述的程式片段輸出的結果為:3 (3) +3 00003123.1235 1.23e+02 1,234,567.12-1,234,567.12|10.123450|| 10.123450||00010.123450|C 風格的輸出功能

C 風格的輸出 (6/6) 我們接著再使用以下的範例程式來說明

System.out.printf() 的用法:

程式執行結果

格式化的輸入 (1/8) 在 Java 5.0 之前的 Java版本中要由控制台

(console) 輸入資料並不是一件直接的工作,我們要使用標準輸入串流物件 System.in 所提供的 read() 方法,由標準輸入串流取得一個位元組的資料,並傳回該位元組的整數值;或特過資料流鏈結 (stream chaining) 的方式將之鏈結InputStreamReader 及 BufferInputReader之後,使用 BufferInputReader 類別的readLine() 方法讀入一個字串。

格式化的輸入 (2/8) 而 Java 5.0 則提供 java.util.Scanner 類別,可以讓

我們方便的進行控制台資料輸入。 例如,在 Java 5.0 之前我們用以下的方式輸入一個整

數 ( 此段程式碼需要捕捉 IOException 例外 ) :import java.io.*;...InputStreamReader 字元資料流 = new

InputStreamReader(System.in);BufferedReader 緩衝字元資料流 = new

BufferedReader( 字元資料流 );String 讀入字串 = 緩衝字元資料流 .readLine();int 輸入整數 = Integer.parseInt( 讀入字串 );

格式化的輸入 (3/8) 在 Java 5.0 之後我們可以使用以下的方式輸入

一個整數 ( 此段程式碼不需要捕捉 IOException例外 ) :

import java.util.*;...Scanner 輸入 = new Scanner(System.in);int 輸入整數 = 輸入 .nextInt( );

格式化的輸入 (4/8) 很顯然的, Scanner 類別提供了相當直接且簡潔的控制台輸入方式,而 Scanner 類別也可以與其他屬於 File 類別、 String 類別或InputStream 類別的物件鏈結 (chaining) 在一起進行檔案、字串中或其他串流的輸入操作。

格式化的輸入 (5/8) 除了 nextInt() 方法之外, Scanner 還提供許多其他的方

法以方便使用者進行輸入操作,以下我們一一介紹: 方法名稱 功能

hasNext() 檢查輸入串流中是否仍有待輸入的 token(輸入單元 )

hasNext(String 比對字串 ) 檢查輸入串流中是否仍有待輸入且與比對字串吻合的 token

hasNextBigDecimal() 檢查下一個待輸入的 token是否能夠輸入為 BigDecimal 物件

hasNextBigInteger() 檢查下一個待輸入的 token是否能夠輸入為 BigInteger 物件

hasNextBigInteger(int 基底參數 ) 檢查下一個待輸入的 token是否能夠輸入為以基底參數為基底的 BigInteger 物件

hasNextBoolean() 檢查下一個待輸入的 token是否能夠輸入為以不區別大小寫的 true/false 建立的布林值

hasNextByte() 檢查下一個待輸入的 token 是否能夠輸入為一個位元組值

hasNextByte(int 基底參數 ) 檢查下一個待輸入的 token是否能夠輸入為一個以基底參數為基底的位元組值

hasNextDouble() 檢查下一個待輸入的 token 是否能夠輸入為一個倍精準度浮點數值

hasNextFloat() 檢查下一個待輸入的 token是否能夠輸入為一個浮點數值

hasNextInt() 檢查下一個待輸入的 token 是否能夠輸入為一個整數值

hasNextInt(int 基底參數 ) 檢查下一個待輸入的 token是否能夠輸入為一個以基底參數為基底的整數值

格式化的輸入 (6/8)hasNextLine() 檢查是否仍有一行待輸入的資料

hasNextLong() 檢查下一個待輸入的 token 是否能夠輸入為一個長整數值

hasNextLong(int 基底參數 ) 檢查下一個待輸入的 token是否能夠輸入為一個以基底參數為基底的長整數值

hasNextShort() 檢查下一個待輸入的 token 是否能夠輸入為一個短整數值

hasNextShort(int 基底參數 ) 檢查下一個待輸入的 token是否能夠輸入為一個以基底參數為基底的短整數值

next() 輸入下一個待輸入的 token (以字串傳回 )

next(String 比對字串 ) 輸入下一個待輸入且與比對字串吻合的 token

nextBigDecimal() 將下一個待輸入的 token輸入為 BigDecimal 物件

nextBigInteger() 將下一個待輸入的 token輸入為 BigInteger 物件

nextBigInteger(int 基底參數 ) 將下一個待輸入的 token是輸入為以基底參數為基底的 BigInteger 物件

nextBoolean() 將下一個待輸入的 token輸入為以不區別大小寫的 true/false 建立的布林值

nextByte() 將下一個待輸入的 token 輸入為一個位元組值

nextByte(int 基底參數 ) 將下一個待輸入的 token輸入為一個以基底參數為基底的位元組值

nextDouble() 將下一個待輸入的 token 輸入為一個倍精準度浮點數值

格式化的輸入 (7/8)nextFloat() 將下一個待輸入的 token輸入為一個浮點數值

nextInt() 將下一個待輸入的 token 輸入為一個整數值

nextInt(int 基底參數 ) 將下一個待輸入的 token輸入為一個以基底參數為基底的整數值

nextLine() 輸入一行資料 (以字串傳回 )

nextLong() 將下一個待輸入的 token 輸入為一個長整數值

nextLong(int 基底參數 ) 將下一個待輸入的 token輸入為一個以基底參數為基底的長整數值

nextShort() 將下一個待輸入的 token 輸入為一個短整數值

nextShort(int 基底參數 ) 將下一個待輸入的 token輸入為一個以基底參數為基底的短整數值

useDelimiter(String 分隔樣板字串 ) 設定以分隔樣板字串來作為區隔 token的依據

delimiter() 取得分隔樣版 ( 以 Pattern物件傳回 )

格式化的輸入 (8/8) 我們使用以下的範例程式來說明 Scanner 類別的應用:

程式執行結果

列舉 (1/5) 在 C/C++ 語言中,我們可以使用 enum 關鍵字

自行定義新的型別 (type) ,在 Java5.0 中也加入了列舉 (enum) 的用法。

Java 5.0 中的列舉也是一種類別,但它使用enum 關鍵字來定義,而且與類別有一些不一樣。

如同所有的類都預設繼承 java.lang.Object 類別一樣,所有的列舉都預設繼承java.lang.Enum 類別,它像一般的類別一樣可以定義方法成員和資料成員,也可以有受限的建構方法 (預設為 private 而且只能是 private) 。

列舉 (2/5) 列舉的語法如下所列:enum 列舉名稱 { 列舉值 1, 列舉值 2, …}其中的列舉值一般習慣以全部大寫的字母命名。

列舉 (3/5) 以下是一個列舉的實例:enum 四季 { 春 , 夏 , 秋 , 冬} // 列舉 :四季 定義區塊結束 這個列舉的名稱為四季,而其中有四個列舉值分

別為春、夏、秋、冬。這些列舉值可以使用四季 . 春、四季 . 夏、四季 . 秋、四季 . 冬來表示。

列舉 (4/5) 以下的範例程式中示範了列舉的使用:

列舉 (5/5)

程式執行結果

靜態引入 (1/3) 在 Java 5.0 中新增了靜態引入 (static import)

的用法,以下我們詳細說明其用法。靜態引入的語法如下所述:

import static 類別庫 .類別 .*;或import static 類別庫 .類別 .方法成員 ;或import static 類別庫 .類別 .資料成員 ;

靜態引入 (2/3) 例如,若我們在程式的開頭加入import static java.lang.Math.*;或加入import static java.lang.Math.random;都可以在後續的程式中直接呼叫 random() 方法,而不需

要在 random() 方法之前再加上 Math 類別名稱 ( 也就是不必使用 Math.random() 來呼叫 ) 。當然,第一個靜態引入敘述使用萬用字元 *,其引用範圍可以涵蓋類別中所有的資料成員與方法成員。

靜態引入 (3/3) 以下範例程式說明靜態引入的用法:

程式執行結果

可變數目參數 (1/4) 在 Java 5.0 中加入了可變數目參數 (variable

arguments) 的用法,配合這個用法,一個方法的最後一個參數可以有變動的數目。

具有可變數目參數方法的宣告語法如下所述:傳回型別 方法識別名稱 ( 參數型別 1 參數名稱 1,

…, 最後參數型別 ... 最後參數名稱 ){ 區域變數宣告 敘述…

return 傳回值 ;}

可變數目參數 (2/4) 例如,以下的程式片段展示一個利用可變數目參

數求出若干個整數總和的方法: int 總和 (int ... 若干整數 ) { int 總和 = 0; for (int i = 0; i < 若干整數 .length; i++) 總和 += 若干整數 [i]; return 總和 ;}

可變數目參數 (3/4) 讀者可以發現可變數目參數變數若干整數與陣列

的用法相同 ( 例如,可以使用 length紀錄長度,可以使用中括號加索引取得某個元素的值 ) ,的確是的,可變數目參數實際上就是透過陣列來實現的。因此,我們可以將可變數目參數變數當作一個陣列來看待。

以下範例程式說明可變數目參數的用法:

可變數目參數 (4/4)

程式執行結果

提 示 在 Java 5.0 中若使用 ArrayList 清單 = new

ArrayList(); 來宣告一個屬於 ArrayList 類別的物件,則仍然可以編譯成功,但是會出現以下的警示字眼:

Note: [ 程式名稱 ].java uses unchecked or unsafe operations.

Note: Recompile with -Xlint:unchecked for details.

執行結果 -1

執行結果 -2

執行結果 -3

執行結果 -4

執行結果 -5

執行結果 -6

執行結果 -7

執行結果 -8

Iterable 說明 Iterable 物件指的屬於實作 Iterable 介面之類別的物件,典型的實作 Iterable 介面之類別包括AbstractCollection, AbstractList, AbstractQueue, AbstractSequentialList, AbstractSet, ArrayBlockingQueue, ArrayList, AttributeList, ConcurrentLinkedQueue, CopyOnWriteArrayList, CopyOnWriteArraySet, DelayQueue, EnumSet, HashSet, JobStateReasons, LinkedBlockingQueue, LinkedHashSet, LinkedList, PriorityBlockingQueue, PriorityQueue, RoleList, RoleUnresolvedList, Stack, SynchronousQueue, TreeSet, Vector 等等。