java se 7 技術手冊第二章草稿 - 從 jdk 到 ide

33
Java SE 7 2.1 "Hello World"開始 開始 開始 開始 "Hello World" Brian Kernighan "A Tutorial Introduction to the Language B" B C "Hello World" "Hello World" " Hello World" "Hello World" 2.1.1 撰寫 撰寫 撰寫 撰寫 Java 原始碼 原始碼 原始碼 原始碼 Windows Windows XP / Windows 7 / Video

Upload: justin-lin

Post on 18-Jul-2015

2.665 views

Category:

Technology


5 download

TRANSCRIPT

Page 1: Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE

Java SE 7技術手冊草稿

2.1 從從從從"Hello World"開始開始開始開始 第一個"Hello World"的出現是在 Brian Kernighan寫的"A Tutorial Introduction to

the Language B"書籍中(B語言是 C語言的前身),用來將"Hello World"文字顯示在電腦螢幕上,自此之後,很多的程式語言教學文件或書籍上,已經無數次地將它當作第一個範例程式。為什麼要用"Hello World"來當作第一個程式範例?因為它很簡單,初學者只要鍵入簡單幾行程式(甚至一行),就可以要求電腦執行指令並得到回饋:"顯示 Hello World"。 本書也要從顯示"Hello World"開始,然而,在完成這簡單的程式之後,千萬要記得,探索這簡單程式之後的種種細節,千萬別過於樂觀地以為,你想從事的程式設計工作就是如此容易駕馭。

2.1.1撰寫撰寫撰寫撰寫 Java原始碼原始碼原始碼原始碼 在正式撰寫程式之前,請先確定你可以看到檔案的副檔名,在 Windows 下預設不顯示副檔名,這會造成重新命名檔案時的困擾,如果目前在「檔案總管」下無法看到副檔名,Windows XP中請先執行工具列上的「工具/資料夾選項」 ,Windows 7下請執行「組合管理/資料夾和搜尋選項」,並切換至「檢視」頁籤,取消「隱藏已知檔案類型的副檔名」之選取。

Video

Page 2: Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE

Java SE 7技術手冊草稿 圖圖圖圖 2.1 取消取消取消取消「「「「隱藏已知檔案類型的副檔名隱藏已知檔案類型的副檔名隱藏已知檔案類型的副檔名隱藏已知檔案類型的副檔名」」」」

接著選擇一個資料夾來撰寫 Java原始碼檔案,本書都是在 C:\workspace資料夾中撰寫程式,請新增「文字文件」(也就是 .txt 文件),並重新命名文件為「HelloWorld.java」,由於將文字文件的副檔名從.txt改為.java,系統會詢問是否更改副檔名,請確定更改,接著在 HelloWorld.java上按右鍵執行「編輯」,就並如下撰寫程式碼:

圖圖圖圖 2.2 第一個第一個第一個第一個 Java程式程式程式程式

提示提示提示提示 Windows 中內建的純文字編輯器並不是很好用,建議你可以使用NotePad++:

� http://notepad-plus-plus.org/

這個檔案撰寫時有幾點必須注意:

� 副檔名是.java 這也就是您必須讓「檔案總管」顯示副檔名的原因。

� 主檔名與類別名稱必須相同 類別名稱是指 class 關鍵字(Keyword)後的名稱,就這個範例子,就是HelloWorld這個名稱,這個名稱必須與HelloWorld.java的主檔名(HelloWorld)相同。

� 注意每個字母大小寫

Java程式區分字母大小寫,System與 system對 Java程式來說是不同的名稱。

� 空白只能是半型空白字元或是 Tab字元

Page 3: Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE

Java SE 7技術手冊草稿 有些初學者可能不小心輸入了全型空白字元,這很不容易檢查出來。

老實說,要對新手解釋第一個 Java 程式並不容易,這個簡單的程式就涉及檔案管理、類別 (Class)定義、程式進入點、命令列引數(Command line argument)等觀念,以下先針對這個範例作基本說明:

定義類別 class是用來定義類別的關鍵字,之後接上類別名稱(HelloWorld),Java程式規定,所有程式碼都要定義在「類別」之中。class 前有個 public 關鍵字,表示 HelloWorld類別是公開類別,就目前為止你只要知道,一個.java檔案可定義數個類別,但是只能有一個公開類別,而且檔案主檔名必須與公開類別名稱相同。

定義區塊(Block) 在程式使用大括號{與}定義區塊,大括號兩兩成對,目的在區別程式碼範圍,例如程式中,HelloWorld類別的區塊包括了 main()方法(Method),而 main()方法的區塊包括了一句顯示訊息的程式碼。

定義 main()方法 程式執行的起點就是程式進入點(Entry point),Java程式執行的起點是 main()方法,規格書中規定 main()方法的形式一定得是:

public static void main(String[] args)

提示提示提示提示 雖然說是規格書中的規定,不過其實日後你理解每個關鍵字的意義,還是可以就每個元素加以解釋。main()方法是 public成員,表示可以被 JVM公開執行,static表示 JVM不用生成類別實例就可以呼叫,Java程式執行過程的錯誤,都是以例外方式處理,所以 main()不用傳回值,宣告為 void 即可,String[] args 可以在執行程式時取得使用者指定的命令列引數。

撰寫陳述(Statement) 來看 main()當中的一行陳述: System.out.println("Hello World"); 陳述是程式語言中的一行指令,簡單地說就是程式語言中的「一句話」。注意每一句陳述的結束要用分號(;),這句陳述的作用,就是請系統的輸出裝置顯示一行文字"Hello World"。

提示提示提示提示 其實你使用了 java.lang 套件(package)中 System 類別的public static 成員 out,out 參考至 PrintStream 實例,

Page 4: Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE

Java SE 7技術手冊草稿 你使用 PrintStream 定義的 println()方法,將指定的字串(String)輸出至文字模式上,println()表示輸出字串後換行,如果使用 print(),輸出字串後不會換行。

其實我真正想說的是:一個基本的 Java 程式這麼寫就對了。一下子要接受如此多觀念確實不容易,如果現階段無法瞭解,就先當這些是 Java 語言文法規範,相關元素在本書之後各章節還會詳細解釋,屆時自然就會了解第一個 Java 程式是怎麼一回事了!

2.1.2PATH是什麼是什麼是什麼是什麼???? 第 1章談過,*.java必須編譯為*.class,才可以在 JVM中執行,Java的編譯器工具程式是 javac,第 1章談過,裝好 JDK之後,工具程式就會放在 JDK安裝資料夾中的 bin資料夾,你必須照第 1章開啟文字模式,如下切換至 C:\workspace,並執行 javac指令:

圖圖圖圖 2.3 喔喔喔喔喔喔喔喔!!!!執行失敗執行失敗執行失敗執行失敗...

失敗了?為什麼?這是(Windows)作業系統在跟你抱怨,它找不到 javac放在哪邊!當要執行一個工具程式,那個指令放在哪,系統預設是不曉得的,除非你跟系統說工具程式存放的位置。例如:

圖圖圖圖 2.4 指定工具程式位置指定工具程式位置指定工具程式位置指定工具程式位置

javac 編譯成功後會靜稍稍地結束,所以沒看到訊息就是好消息,但是這樣下指令實在太麻煩了,而且你會有疑問:第 1 章安裝 JDK 最後示範執行 java 指令時,為什麼不用指定位置? 當你鍵入一個指令而沒有指定路徑資訊時,作業系統會依照 PATH環境變數中設定的路徑順序,依序尋找各路徑下是否有這個指令。可以執行 echo %PATH%來看看

Page 5: Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE

Java SE 7技術手冊草稿 目前系統 PATH環境變數中包括哪些路徑資訊:

圖圖圖圖 2.5 察看察看察看察看 PATH資訊資訊資訊資訊 依圖 2.5的 PATH資訊,如果你鍵入 java指令,系統會從第一個路徑開始找有無java(.exe)工具程式,如果沒有再找下一個路徑有無 java(.exe)工具程式...找到的話就執行。若你查看 C:\Windows\system32,會發現當中確實有 java(.exe),這是因為安裝 JDK(JRE)時,Windows 的 JDK(JRE)安裝程式會自動放一份 java(.exe)到C:\Windows\system32,這就是為何第 1章安裝 JDK(JRE)後,就可以直接執行 java指令的原因。 然而依圖 2.5的 PATH資訊,如果鍵入 javac指令,系統找完 PATH中所有路徑後,都不會找到 javac (.exe)工具程式,當所有路徑都找不到指定的工具程式時,就會出現剛剛圖 2.3的錯誤訊息。 你要在 PATH中設定工具程式的路徑資訊,系統才可以在 PATH中找到你要執行的指令。如果要設定 PATH,可以使用 SET指令來設定,設定方式為 SET PATH=路路路路徑徑徑徑。例如:

圖圖圖圖 2.6 設定設定設定設定 PATH環境環境環境環境變數變數變數變數 設定時若有多個路徑,會使用分號(;)作區隔,通常會將原有 PATH 附加在設定值後面,如此尋找其它指令時,才可以利用原有的 PATH資訊。設定完成之後,就可以執行 javac而不用額外指定路徑。 不過在文字模式中設定,關掉這個文字模式後,下次要開啟文字模式又要重新設定。為了方便,可以在「使用者環境變數」或「系統環境變數」中設定 PATH。在Windows XP可以選取桌面上「我的電腦」並按滑鼠右鍵執行「內容」,Windows 7中要再按下「進階系統設定」,進入「系統內容」,接著切換至「進階」頁面,按下方的「環境變數」按鈕,在環境變數對話方塊中的「使用者環境變數」或「系統環境變數」編輯「PATH」變數:

Video

Page 6: Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE

Java SE 7技術手冊草稿

圖圖圖圖 2.7 設定使用者變數或系統變數設定使用者變數或系統變數設定使用者變數或系統變數設定使用者變數或系統變數 在一個可以允許多人共用的系統中,系統環境變數的設定,會套用至每個登入的使用者,而使用者環境變數只影響個別使用者。開啟一個文字模式時,獲得的環境變數,會是系統環境變數再「附加」使用者環境變數。如果使用 SET 指令設定環境變數,則以 SET所設定的結果決定。 以設定系統變數為例,可如圖 2.7選取 Path變數後,按下「編輯」按鈕,於「變數 值 」 欄 位 的 最 前 方 輸 入 JDK 「 bin 」 目 錄 的 路 徑 ( C:\Program

Files\Java\jdk1.7.0\bin),然後緊跟著一個分號,作為路徑設定區隔,接著按「確定」完成設定。

圖圖圖圖 2.8 編輯編輯編輯編輯 Path系統變數系統變數系統變數系統變數

Page 7: Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE

Java SE 7技術手冊草稿 建議將 JDK的 bin路徑放在 Path變數的最前方,是因為系統搜尋 Path路徑時,會從最前方開始,如果路徑下找到指定的工具程式就會直接執行,若系統中安裝兩個以上 JDK時,Path路徑中設定的順序,將決定執行哪個 JDK下的工具程式,在安裝了多個 JDK或 JRE的電腦中,確定執行了哪個版本的 JDK或 JRE非常重要,確定確定確定確定PATH資訊是一定要作的動作資訊是一定要作的動作資訊是一定要作的動作資訊是一定要作的動作。

提示提示提示提示 由於開啟文字模式時獲得的環境變數,會是系統環境變數附加使用者環境變數,若系統環境變數 PATH 中已經設定好某個 JDK,即使你在使用者環境變數 PATH中將想要的 JDK路徑設在最前頭,也會執行到系統環境變數 PATH 中設定的 JDK。如果你有足夠權限修改系統環境變數,建議修改系統環境變數 PATH。如果沒有權限變更,那就使用SET 指令,因為使用 SET 指令設定環境變數,會以 SET 設定的結果決定。

2.1.3JVM((((java))))與與與與 CLASSPATH

在如圖 2.6 完成編譯 HelloWorld.java 之後,相同資料夾下就會出現HelloWorld.class,第 1 章說過,JVM 的可執行檔副檔名是的可執行檔副檔名是的可執行檔副檔名是的可執行檔副檔名是.class,接下來要啟動要啟動要啟動要啟動JVM,,,,要求要求要求要求 JVM執行執行執行執行 HelloWorld指令指令指令指令:

圖圖圖圖 2.9 第一個第一個第一個第一個 Hello World出現了出現了出現了出現了

如圖 2.9所示,啟動 JVM的指令是 java,而要求 JVM執行 HelloWorld時,只要指定類別名稱(就像執行 javac.exe工具程式,只要鍵入 javac就可以了),不用附加.class副檔名,附加.class反而會有錯誤訊息。

接下來,請你試著切換至 C:\,想想看,如何執行 HelloWorld?以下幾個方式都是行不通的:

Page 8: Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE

Java SE 7技術手冊草稿

圖圖圖圖 2.10 怎麼執行怎麼執行怎麼執行怎麼執行 HelloWorld呢呢呢呢???? 你要知道 java這個指令是作什麼用的?正如先前所言,執行執行執行執行 java指令指令指令指令目的目的目的目的在於在於在於在於啟動啟動啟動啟動 JVM,,,,之後接之後接之後接之後接著著著著類別名稱類別名稱類別名稱類別名稱,,,,表示表示表示表示要求要求要求要求 JVM執行執行執行執行指定的可執行檔指定的可執行檔指定的可執行檔指定的可執行檔((((.class))))。

在「PATH 是什麼?」中提過,實體作業系統下執行某個指令時,會依 PATH中的路徑資訊,試圖找到可執行檔案(例如對 Windows 來說,就是.exe、.bat 副檔名的檔案,對 Linux等就是有執行權限的檔案)。

從第 1章就一直強調,JVM是 Java程式唯一認得的作業系統,對 JVM來說,可執行檔就是副檔名為.class 的檔案。想在 JVM 中執行某個可執行檔(.class),你就要告訴 JVM這個虛擬作業系統到哪些路徑下尋找檔案,方式是透過 CLASSPATH指定其可執行檔(.class)的路徑資訊。 用 Windows 與 JVM 作個簡單的對照,就可以很清楚地對照 PATH 與CLASSPATH: 表 2.1 PATH與 CLASSPATH 作業系統作業系統作業系統作業系統 搜尋搜尋搜尋搜尋路徑路徑路徑路徑 可執行檔可執行檔可執行檔可執行檔

Windows PATH .exe、.bat

JVM CLASSPATH .class

注意注意注意注意 PATH與 CLASSPATH根本就是不同層次的環境變數,實體作業系統搜尋可執行檔是看 PATH,JVM 搜尋可執行檔(.class)只看CLASSPATH。

如何在啟動 JVM時告知可執行檔(.class)的位置?可以使用-classpath引數來指定:

Page 9: Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE

Java SE 7技術手冊草稿

圖圖圖圖 2.11 啟動啟動啟動啟動 JVM時指定時指定時指定時指定 CLASSPATH

如圖 2.11所示,-classpath有個縮寫形式-cp,這比較常用。如果有多個路徑資訊,則可以用分別區隔。例如:

java -cp C:\workspace;C:\classes HelloWorld

JVM 會依 CLASSPATH 路徑順序,搜尋是否有對應的類別檔案,先找到先贏,先找到先載入。如果在 JVM的 CLASSPATH路徑資訊中都找不到指定的類別檔案,JDK7前的版本會出現 java.lang.NoClassDefFoundError訊息,而 JDK7後的版本會有比較友善的中文錯誤訊息(如圖 2.10)。 為什麼圖 2.9不用特別指定 CLASSPATH呢?JVM預設的預設的預設的預設的 CLASSPATH就就就就是是是是讀讀讀讀取目前資料夾中取目前資料夾中取目前資料夾中取目前資料夾中的的的的.class,,,,如果如果如果如果自行指定自行指定自行指定自行指定 CLASSPATH,,,,則以你指定的為主則以你指定的為主則以你指定的為主則以你指定的為主。。。。例如:

圖圖圖圖 2.12 指定的指定的指定的指定的 CLASSPATH中找不到中找不到中找不到中找不到類別檔案類別檔案類別檔案類別檔案 如上圖所示,雖然工作路徑是在 C:\workspace(其中有 HelloWorld.class),你啟動 JVM 時指定到 C:\xyz 中搜尋類別檔案,JVM 還是老實地到指定的 C:\xyz 中找尋,結果當然就是找不到而顯示錯誤訊息。有的時候,希望也從目前資料夾開始尋找類別檔案,則可以使用.指定。例如:

圖圖圖圖 2.12 指定指定指定指定.表示搜尋類別檔案時包括目前資料夾表示搜尋類別檔案時包括目前資料夾表示搜尋類別檔案時包括目前資料夾表示搜尋類別檔案時包括目前資料夾

Page 10: Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE

Java SE 7技術手冊草稿 如果使用 Java開發了程式庫,這些程式庫中的類別檔案,會封裝為 JAR((((Java

Archive))))檔案,也就是副檔名為.jar的檔案。JAR檔案實際使用 ZIP格式壓縮,當中包含一堆.class檔案,那麼,如果你有個 JAR檔案,如何在 CLASSPATH中設定? 答案是將 JAR檔案當作特別的資料夾,例如,有 abc.jar與 xyz.jar放在 C:\lib底下,執行時若要使用 JAR檔案中的類別檔案,可以如下:

java -cp C:\workspace;C:\lib\abc.jar;C:\lib\xyz.jar SomeApp 如果有些類別路徑很常使用,其實也可以透過環境變數設定。例如:

SET CLASSPATH=C:\classes;C:\lib\abc.jar;C:\lib\xyz.jar

在啟動 JVM 時,也就是執行 java 時,若沒使用 -cp 或 -classpath 指定CLASSPATH,就會讀取 CLASSPATH環境變數。同樣地,文字模式中的設定在關閉文字模式之後就會失效。如果希望每次開啟文字模式都可以套用某個 CLASSPATH,也可以設定在系統變數或使用者變數中。如果執行時,使用了-cp 或-classpath 指定CLASSPATH,則以-cp或-classpath的指定為主。 如果某個資料夾中有許多.jar檔案,從 Java SE 6開始,可以使用*表示使用資料夾中所有.jar檔案。例如指定使用 C:\jars下所有 JAR檔案:

java –cp .;C:\jars\* cc.openhome.JNotePad

Java SE 6中 Classpath新的指定方式,也適用在系統環境變數的設定上。

提示提示提示提示 CLASSPATH其實是給應用程式類別載入器(AppClassLoader)使用的資訊,想要了解類別載入方式,則要了解類別載入器機制,這是進階議題,本書後面才會談到。

2.1.4編譯編譯編譯編譯器器器器((((javac))))與與與與 CLASSPATH

在光碟中 labs/CH2資料夾中有個 classes資料夾,請將之複製至 C:\workspace中,確認 C:\workspace\classes 中有個已編譯好 Console.class,你可以在C:\workspace中開個 Main.java,如下使用 Console類別:

圖圖圖圖 2.13 使使使使用已編譯好的用已編譯好的用已編譯好的用已編譯好的.class檔案檔案檔案檔案

如果你如下編譯,將會出現錯誤訊息:

Lab

Page 11: Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE

Java SE 7技術手冊草稿

圖圖圖圖 2.14 找不到找不到找不到找不到 Console類別的編譯錯誤類別的編譯錯誤類別的編譯錯誤類別的編譯錯誤

編譯器在抱怨,它找不到 Console類別在哪裡(cannot find symbol),事實上,在使用在使用在使用在使用 javac 編譯器編譯器編譯器編譯器時時時時,,,,如果要使用到如果要使用到如果要使用到如果要使用到其它類別其它類別其它類別其它類別程式庫時程式庫時程式庫時程式庫時,,,,也必須指定也必須指定也必須指定也必須指定CLASSPATH,告訴 javac編譯器到哪邊尋找.class檔案。例如:

圖圖圖圖 2.15 編譯成功編譯成功編譯成功編譯成功,,,,但執行時找不到但執行時找不到但執行時找不到但執行時找不到 Console類別類別類別類別的錯誤的錯誤的錯誤的錯誤

這一次編譯成功了,但無法執行,原因是執行時找不到 Console類別,因為你執行時忘了跟 JVM指定 CLASSPATH,所以 JVM找不到 Console類別。如果如下執行就可以了:

圖圖圖圖 2.16 找到找到找到找到 Console與與與與 Main執行成功執行成功執行成功執行成功

別忘了,如果執行 JVM時指定了 CLASSPATH,就只會在指定的 CLASSPATH中尋找使用到的類別,所以圖 2.16 指定 CLASSPATH 時,是指定「.;classes」,注

Page 12: Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE

Java SE 7技術手冊草稿 意一開始的「.」,這表示目前資料夾,這樣才可以找到目前資料夾下的 Main.class,以及 classes下的 Console.class。

提示提示提示提示 你知道嗎?javac等工具程式,大多也是 Java撰寫的,執行於 JVM之上,這也就是為何, javac 需要相關 .class 檔案路徑資訊時,也是用CLASSPATH指定的原因,以下網址有進一步探討:

� http://caterpillar.onlyfun.net/Gossip/JavaEssence/ChickenOrEggFirst.html

2.2 管理原始碼與位元碼檔案管理原始碼與位元碼檔案管理原始碼與位元碼檔案管理原始碼與位元碼檔案 來觀察一下目前你的 C:\workspace,原始碼(.java)檔案與位元碼檔案(.class)都放在一起,想像一下,如果程式規模稍大,一堆.java與.class檔案還放在一起,會有多麼混亂,你需要有效率地管理原始嗎與位元碼檔案。

2.2.1編譯器編譯器編譯器編譯器((((javac))))與與與與 SOURCEPATH

首先必須先解決原始碼檔案與位元碼檔案都放在一起的問題。請將光碟中 labs資料夾的 Hello1資料夾複製至 C:\workspace中,Hello1資料夾中有 src與 classes資料夾,src資料夾中有 Console.java與 Main.java兩個檔案,其中 Console.java就是 2.1.4中 Console類別的原始碼(目前你不用關心它如何撰寫),而 Main.java的內容與圖 2.13相同。

簡單地說,src 資料夾將用來放置原始碼檔案,而編譯好的位元碼檔案,希望能指定存放至 classes資料夾。你可以在文字模式下,切換至 Hello1資料夾,然後如下進行編譯:

圖圖圖圖 2.17 指定指定指定指定-sourcepath與與與與-d進行編譯進行編譯進行編譯進行編譯

在編譯 src/Main.java時,由於程式碼中要使用到 Console類別,你必須告訴編譯器,Console類別的原始碼檔案存放位置,這邊使用-sourcepath指定從 src資料夾中尋找原始碼檔案,而-d指定了編譯完成的位元碼存放資料夾,編譯器會將使用到的相關類別原始碼也一併進行編譯,編譯完成後,會在 classes 資料夾中看到Console.class與 Main.class檔案。你可以如下執行程式:

Lab

Page 13: Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE

Java SE 7技術手冊草稿

圖圖圖圖 2.18 指定指定指定指定執行執行執行執行 classes中的中的中的中的 Main類別類別類別類別

你可以在編譯時指定-verbose 引數,看到編譯器進行編譯時的過程,這有助於了解 SOURCEPATH與 CLASSPATH的差別:

圖圖圖圖 2.19 編譯時指定編譯時指定編譯時指定編譯時指定-verbose

就初學而言,最主要看看虛線部份,在編譯時,會先搜尋-sourcepath 指定的資料夾(上例指定 src)�是不是有使用到的類別原始碼,然後會搜尋 CLASSPATH中,是否有已編譯的類別位元碼�,你可以發現,其實預設搜尋位元碼的路徑包括許多預設的 JAR檔案,像是 rt.jar等,留意最後那那個「.」,由於沒有指定-classpath(-cp),預設會搜尋目前路徑。

確認原始碼與位元碼搜尋路徑之後,接著檢查 CLASSPATH 中是否已經有編譯完成的 Main 類別,如果存在且從上次編譯後,Main 類別的原始碼並沒有改變,則

Page 14: Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE

Java SE 7技術手冊草稿 無需重新編譯,如果不存在,則重新編譯 Main類別,就上例而言,由於 CLASSPATH並不包括 classes資料夾,所以找不到 Main類別位元碼,因此重新編譯出Main.class並存放至 classes中�。

接著檢查 CLASSPATH中是否已經有編譯完成的 Console類別,如果存在且從上次編譯後,Console 類別的原始碼並沒有改變,則無需重新編譯,如果不存在,則重新編譯 Console類別,就上例而言,由於 CLASSPATH並不包括 classes資料夾,所以找不到 Console 類別位元碼,因此重新編譯出 Console.class 並存放至classes中�。

實際專案中會有數以萬計的類別,如果每次都要重新將.java編譯為.class,那會是非常費時的工作,所以編譯時若類別路徑中已存在位元碼,且上次編譯後,原始碼並沒有修改,無需重新編譯會比較節省時間,因此,就上例而言,應該指定-cp 為classes。例如:

圖圖圖圖 2.20 編譯時指定編譯時指定編譯時指定編譯時指定-sourcepath與與與與-cp

注意到,這次指定了-sourcepath為 src,而-cp為 classes,所以會在 src中搜尋位原始碼檔案�,在 classes 中搜尋位元碼檔案�(注意最後的 classes),由於CLASSPATH中包括 classes資料夾,所以找到 Console類別位元碼,因此無需重新編譯 Console.class,而只編譯 javac指定的Main.java為 Main.class�。

提示提示提示提示 JVM預設的類別搜尋路徑,也就是那些 JAR檔案的搜尋路徑,其實與類別載入器有關,這是個進階議題,之後章節會加以討論。

Page 15: Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE

Java SE 7技術手冊草稿

2.2.2使用使用使用使用 package管理類別管理類別管理類別管理類別

現在你所撰寫的類別,.java放在 src資料夾中,編譯出來的.class放置在 classes資料夾下,就檔案管理上比較好一些了,但還不是很好,就如同你會分不同資料夾來放置不同作用的檔案,類別也應該分門別類加以放置。

舉例來說,一個應用程式中會有多個類別彼此合作,也有可能由多個團隊共同分工,完成應用程式的某些功能塊,再組合在一起,如果你的應用程式是多個團隊共同合作,若不分門別類放置.class,那麼若 A部門寫了個 Util類別並編譯為 Util.class,B部門寫了個 Util類別並編譯為 Util.class,當他們要將應用程式整合時,就會發生檔案覆蓋的問題,而如果現在要統一管理原始碼,也許原始碼也會發生彼此覆蓋問題。

你要有個分門別類管理類別的方式,無論是實體檔案上的分類管理,或是類別名稱上的分類管理,在 Java 語法中,有個 package 關鍵字,可以協助你達到這個目的。

請用編輯器開啟 2.2.2中 Hello1/src資料夾中的 Console.java,在開頭鍵入下圖反白的文字:

圖圖圖圖 2.21 將將將將 Console類別放在類別放在類別放在類別放在 cc.openhome.util分類分類分類分類

這表示,Console類別將放在 cc.openhome.util的分類下,以 Java的術語來說,Console這個類別將放在 cc.openhome.util套件套件套件套件((((package))))。 請再用文字編輯器開啟 2.2.2中 Hello1/src資料夾中的 Main.java,在開頭鍵入下圖反白的文字,這表示 Console類別將放在 cc.openhome的分類下:

圖圖圖圖 2.22 將將將將 Main類別放在類別放在類別放在類別放在 cc.openhome分類分類分類分類

提示提示提示提示 套件的命名,通常會用組織或單位的網址命名,舉例來說,我的網址是opehome.cc,套件就會反過來命名為 cc.openhome,由於組織或單位的網址是獨一無二的,這樣的命名方式,比較不會與其它組織或單位的套件名稱發生同名衝突。

當類別原始碼開始使用 package進行分類時,就會具有四種管理上的意義:

Lab

Page 16: Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE

Java SE 7技術手冊草稿

� 原始碼檔案要放置在與 package所定義名稱階層相同的資料夾階層

� package 所定義名稱與 class 所定義名稱,會結合而成類別的完全吻合名稱完全吻合名稱完全吻合名稱完全吻合名稱((((Fully qualified name))))

� 位元碼檔案要放置在與 package所定義名稱階層相同的資料夾階層

� 要在套件間可以直接使用的類別或方法(Method)必須宣告為 public 關於第 4點,牽涉到套件間的權限管理,將在下一章介紹,本章先不予討論,以下針對 1到 3點分別作說明。

原始碼檔案與套件管理 目前計劃將所有原始碼檔案放在 src 資料夾中管理,由於 Console 類別使用package定義在 cc.openhome.util套件下,所以 Console.java必須放在 src資料夾中的 cc/openhome/util資料夾,在沒有工具輔助下,你必須手動建立出資料夾,Main 類別使用 package 定義在 cc.openhome 套件下,所以 Main.java 必須放在src資料夾中的 cc/openhome資料夾。

這麼作的好處很明顯,日後若不同組織或單位的原始碼要放置在一起管理,就不容易發生原始碼檔案彼此覆蓋的問題。

完全吻合名稱(Fully qualified name) 由於 Main 類別是位於 cc.openhome 套件分類中,其完全吻合名稱是cc.openhome.Main,而 Console 類別是位於 cc.openhome.util 分類中,其完全吻合名稱為 cc.openhome.util.Console。

在原始碼中指定使用某個類別時,如果是相同套件中的類別,只要使用 class所定義的名稱即可,而不同套件的類別,必須使用完全吻合名稱。由於 Main 與Console類別是位於不同的套件中,在 Main類別中要使用 Console類別,就必須使用 cc.openhome.util.Console,也就是說,Main.java現在必須修改為:

圖圖圖圖 2.23 使用完全吻合名稱使用完全吻合名稱使用完全吻合名稱使用完全吻合名稱

這麼作的好處在於,若另一個組織或單位也使用 class 定義了 Console,但其套件定義為 com.abc,則其完全吻合名稱為 com.abc.Console,也就不會與你的 cc.openhome.util.Console發生名稱衝突問題。

Page 17: Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE

Java SE 7技術手冊草稿

位元碼檔案與套件管理 目前計劃將所有位元碼檔案放在 class 資料夾中管理,由於 Console 類別使用package 定義在 cc.openhome.util 套件下,所以編譯出來的 Console.class 必須放在 classes資料夾中的 cc/openhome/util資料夾,Main類別使用 package定義在 cc.openhome 套件下,所以 Main.class 必須放在 classes 資料夾中的cc/openhome資料夾。

你不用手動建立對應套件階層的資料夾,在編譯時若有使用-d指定位元碼的存放位置,就會自動建立出對應套件階層的資料夾,並將編譯出來的位元碼檔案放置至應有的位置。例如:

圖圖圖圖 2.24 指定指定指定指定-d引數引數引數引數,,,,會建立對應套件的資料夾階層會建立對應套件的資料夾階層會建立對應套件的資料夾階層會建立對應套件的資料夾階層

注意!由於 Main 類別位於 cc.openhome 套件中,所以上圖使用 java 執行程式時,必須指定完全吻合名稱,也就是指定 cc.openhome.Main這個名稱。

2.2.3使用使用使用使用 import偷懶偷懶偷懶偷懶

使用套件管理,解決了實體檔案與撰寫程式時類別名稱衝突的問題,但若每次撰寫程式時,都得鍵入完全吻合名稱,卻也是件麻煩的事,想想看,有些套件定義的名稱很長時,單是要鍵入完全吻合名稱得花多少時間。

你可以用 import偷懶一下,例如:

圖圖圖圖 2.25 使用使用使用使用 import減少打字麻煩減少打字麻煩減少打字麻煩減少打字麻煩 編譯與執行時的指令方式,與圖 2.24相同。當編譯器剖析Main.java看到 import宣告時,會先記得 import的名稱,後續剖析程式時,若看到 Console名稱,原本

Lab

Page 18: Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE

Java SE 7技術手冊草稿 會不知道 Console是什麼東西,但編譯器記得你用 import告訴過它,如果遇到不認 識 的 名 稱 , 可 以 比 對 一 下 import 過 的 名 稱 , 編 譯 器 試 著 使 用cc.openhome.util.Console,結果可以在指定的類別路徑中,cc/openhome/util資料夾下找到 Console.class,於是可以進行編譯。 所以 import只是告訴編譯器,遇到不認識的類別名稱,可以嘗試使用 import過的名稱,import讓你少打一些字,讓編譯器多為你作一些事。 如果同一套件下會使用到多個類別,你也許會多次使用 import:

import cc.openhome.Message;

import cc.openhome.User;

import cc.openhome.Address; 你可以更偷懶一些,用以下的 import語句: import cc.openhome.*;

圖 2.25也可以使用以下的 import語句,而編譯與執行結果相同:

import cc.openhome.util.*; 當 編 譯 器 剖 析 Main.java 看 到 import 的 宣 告 時 , 會 先 記 得 有cc.openhome.util 套件名稱,在後續剖析到 Console 名稱時,發現它不認識Cosnole是什麼東西,但編譯器記得你用 import告訴過它,若遇到不認識的名稱,可以比對一下 import過的名稱,編譯器試著將 cc.openhome.util與 Console結合為 cc.openhome.util.Console,結果可以在指定的類別路徑中,cc/openhome/util資料夾下找到 Console.class,於是可以進行編譯。 偷懶也是有個限度,如果你自己寫了一個 Arrays:

package cc.openhome;

public class Arrays {

...

} 若在某個類別中撰寫有以下的程式碼:

import cc.openhome.*;

import java.util.*;

public class Some {

public static void main(String[] args) {

Arrays arrays;

...

}

}

那麼編譯時,你會發現有以下錯誤訊息:

Page 19: Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE

Java SE 7技術手冊草稿

圖圖圖圖 2.26 到底是用哪個到底是用哪個到底是用哪個到底是用哪個 Arrays???? 當編譯器剖析 Some.java 看到 import 的宣告時,會先記得有 cc.openhome套件名稱,在繼續剖析至 Arrays該行時,發現它不認識 Arrays是什麼東西,但編譯器記得你用 import告訴過他,若遇到不認識的名稱,可以比對 import過的名稱,編譯器試著將 cc.openhome 與 Arrays 結合在一起為 cc.openhome.Arrays,結果可以在類別路徑中,cc/openhome資料夾下找到 Arrays.class。 然 而 , 編 譯 器 試 著 將 java.util 與 Arrays 結 合 在 一 起 為java.util.Arrays,發現也可以在 Java SE API的 rt.jar中(預設的類別載入路徑之一,參考圖 2.20),對應的 java/util 資料夾中找到 Arrays.class,於是編譯器困惑了,到底該使用 cc.openhome.Arrays還是 java.util.Arrays? 遇到這種情況時,就不能偷懶了,你要使用哪個類別名稱,就得明確地逐字打出來:

import cc.openhome.*;

import java.util.*;

public class Some {

public static void main(String[] args) {

cc.openhome.Arrays arrays;

...

}

} 這個程式就可以通過編譯了。簡單地說,import是偷懶工具是偷懶工具是偷懶工具是偷懶工具,,,,不能偷懶就回歸不能偷懶就回歸不能偷懶就回歸不能偷懶就回歸最保守的寫法最保守的寫法最保守的寫法最保守的寫法。 提示提示提示提示 學過 C/C++的讀者請注意,import 跟#include 一點都不像,無論原始碼中有無 import,編譯過後的.class都是一樣的,不會影響執行效能。import頂多只會讓編譯時的時間拉長一些而已。

在 Java SE API中有許多常用類別,像是寫第一個 Java程式時使用的 System類別,其實也有使用套件管理,完整名稱其實是 java.lang.System,在java.lang 套件下的類別由於很常用,不用撰寫 import 也可以直接使用 class定義的名稱,這也就是為何不用如下撰寫程式的原因(寫了當然也沒關係,只是自找麻煩):

Page 20: Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE

Java SE 7技術手冊草稿

java.lang.System.out.println("Hello!World!"); 如果類別位於同一套件,彼此使用並不需要 import,當編譯器看到一個沒有套件管理的類別名稱,會先在同一套件中尋找類別,如果找到就使用,若沒找到,再試著從 import 陳述進行比對。java.lang 可視為預設就有 import,沒有寫任何import陳述時,也會試著比對 java.lang的組合,看看是否能找到對應類別。

提示提示提示提示 原始碼檔案或位元碼檔案,都可以使用 JAR檔案封裝,在文字模式下,可以使用 JDK的 jar工具程式來製作 JAR檔案,你可以參考以下文件:

� http://caterpillar.onlyfun.net/Gossip/JavaEssence/SourceClassInJAR.html

2.3 使用使用使用使用 IDE 在開始使用套件管理原始碼檔案與位元碼檔案之後,你必須建立與套件對應的實體資料夾階層,編譯時必須正確指定-sourcepath、-cp等引數,執行程式時必須使用完全吻合名稱,這 ...實在是很麻煩!你可以考慮開始使用 IDE( Integrated

Development Environment),由 IDE代勞你一些原始碼檔案與位元碼檔案等資源管理工作,提昇你的產能。

提示提示提示提示 除了 IDE之外,也可以考慮使用 Ant或 Maven等工具提昇產能,可以參考以下文件中有關 Ant或Maven的說明:

� http://caterpillar.onlyfun.net/Gossip/JUnit/

2.3.1IDE專案管理專案管理專案管理專案管理基礎基礎基礎基礎 在 Java 的領域中,有為數不少的 IDE,其中有不少是優秀的開放原始碼產品,最為人熟知的 IDE有像是 NetBeans、Eclipse、Intellij IDEA、JDeveloper等,不同的 IDE 會有不同的特色,但基本觀念通常相同,最重要的是,只要你瞭解 JDK 與相關指令操作,就不容易被特定的 IDE給限制住。 在本書中,將選擇 NetBeans IDE 7進行基本介紹,必要時提示 Eclipse對應的功能,選擇 NetBeans的原因在於,NetBeans直接使用你安裝的 JDK,而 IDE上顯示的編譯錯誤訊息就是 JDK實際顯示的訊息,這對初學者瞭解 JDK與 IDE功能對應有幫助。提示 Eclipse 對應功能的原因在於,它有許多外掛(plugin)可以使用,可讓你打造屬於自己的 IDE,許多商業用 IDE也多以 Eclipse作為基礎。 你可以至以下網址下載 NetBeans IDE,就本書範圍而言,只要下載 Java SE版本即可:

� http://netbeans.org/downloads/index.html 對 於 Windows 使 用 者 , 可 以 直 接 使 用 光 碟 中 tools 資 料夾 中 的

Page 21: Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE

Java SE 7技術手冊草稿

netbeans-7.0-ml-javase-windows.exe,按下可執行檔並同意授權後,出現以下畫面時,請選擇你的 JDK7安裝目錄,之後逐步按照指示進行安裝即可:

圖圖圖圖 2.27 NetBeans IDE直接使用你安裝的直接使用你安裝的直接使用你安裝的直接使用你安裝的 JDK

提示提示提示提示 Eclipse的下載頁面如下,對本書範圍而言,只要下載Eclipse IDE for Java

Developers即可:

� http://www.eclipse.org/downloads/

Eclipse無需安裝,只要安裝有 JRE,將下載的檔案解壓縮後,按一下當中的 eclipse就可以運行,Eclipse不使用 JDK的開發工具,它有自己的Java開發工具(Java Development Tools,JDT),詳細資訊可參考:

� http://www.eclipse.org/jdt/

在程式規模步入必須使用套件管理之後,你就等於初步開始了專案資源管理,在IDE中要撰寫程式,通常也是從建立專案開始。在 NetBeans中,可以如下建立專案:

1. 執行選單「File/New Project...」,在出現的「New Project」對話方塊中,「Categories」選擇「Java」,而「Projects」選擇「Java Application」,接著按下「Next」按鈕。

2. 在「Project Name:」中輸入專案名稱「Hello2」,「Project Location:」輸入「C:\workspace」,注意「Project Folder:」會儲存至「C:\workspace\Hello2」。

3. 在「Create Main Class」中輸入「cc.openhome.Main」,這表示會有個 Main類Video

Page 22: Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE

Java SE 7技術手冊草稿 別放在 cc.openhome套件,當中會自動建立 main()程式進入點方法,接著按下「Finish」按鈕建立專案。 專案建立後,IDE通常會提供預設的專案檢視窗格,方便你檢視一些專案資源,NetBeans的話,提供如下圖的「Projects」窗格:

圖圖圖圖 2.28 NetBeans IDE的的的的 Projects窗格窗格窗格窗格

在上圖的 Projects 窗格中,可以看到「Source Packages」中有套件檢視cc.openhome,其中放置了 Main.java,這方便你以套件為單位檢視原始碼檔案,而「Libraries」中可看到使用了 JDK 1.7中的一些 JAR檔案,你可以回顧圖 2.19中的CLASSPATH,就有這些 JAR檔案。Libraries中出現的 JAR檔案,表示 IDE管理的CLASSPATH會包括這些 JAR檔案。

你可以在Main.java中如下撰寫,然後執行選單中「Run/Build Main Project」,這會要求 NetBeans進行程式編譯:

System.out.println("Hello World");

Projects窗格提供方便的專案資源檢視,但不等於實體檔案管理,有的 IDE必須自行開啟「檔案總管」來觀看專案資料夾內容,NetBeans則可以切換至「Files」窗格直接檢視實際實體檔案管理:

Page 23: Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE

Java SE 7技術手冊草稿

圖圖圖圖 2.29 NetBeans IDE的的的的 Files窗格窗格窗格窗格

上圖就是目前專案資料夾 C:\workspace\Hello2的實體內容,就目前來說,可先注意 Files 窗格中的「build/classes」、「dist」與「src」資料夾。「build/classes」就是編譯出來的位元碼檔案(所以也是執行時會用到的 CLASSPATH),當中會自動依package 定義名稱分門別類放置.class 檔案,「dist」資料夾就是封裝了位元碼檔案的 JAR 檔案,「src」資料夾就是原始碼檔案,當中會自動依 package 定義名稱分門別類放置.java檔案,這一切都是 IDE代勞,畢竟 IDE是產能(Productivity)工具。

如果要使用 NetBeans執行有程式進入點 main()的類別,可於類別上按右鍵執行「Run File」指令,會有個「Output」窗格顯示執行結果。

在 IDE中編輯程式碼,若出現紅色虛線,通常表示那是導致編譯錯誤的語法,如果看到紅色虛線千萬別發愣,把滑鼠游標移至紅色虛線上,就會顯示的編譯錯誤,如果是 NetBeans,會直接顯示 JDK 編譯工具提供的錯誤訊息。例如下圖是 Main.java中,public class定義的名稱不等於 Main(主檔名)而產生的編譯錯誤與訊息:

Page 24: Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE

Java SE 7技術手冊草稿

圖圖圖圖 2.30 在在在在 IDE中中中中,,,,紅色虛線通常表示編譯錯誤紅色虛線通常表示編譯錯誤紅色虛線通常表示編譯錯誤紅色虛線通常表示編譯錯誤

對於一些編譯錯誤,如果 IDE夠聰明,也許會提示一些改正方式,以 NetBeans來說,會出現一個小電燈炮圖示,這時可以按下圖示顯示改正提示,看看是否有合用的選項:

圖圖圖圖 2.31編譯錯誤時的改正提示編譯錯誤時的改正提示編譯錯誤時的改正提示編譯錯誤時的改正提示

以上圖為例,是因為編譯器不認得 Scanner類別,第一個選項是因為,編譯器發現有個 java.util.Scanner 也許是你想要的,看你是不是要 import,你也可以看到,在另一個套件分類中,也有個 Scanner,另外還有建立類別的兩個選項,編譯器有提示是好事,但你還是要判斷哪個選項才是你想要的,不是按下第一個選項就沒事了。

提示提示提示提示 Eclipse有許多操作是類似的,不過 Eclipse使用自己的 JDT,所以編譯的錯誤訊息不是 JDK提供的訊息,下圖顯示 Eclipse的一些基本畫面:

Page 25: Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE

Java SE 7技術手冊草稿

以上稍微解釋了至今為止,CLASSPATH、JDK工具使用、編譯相關錯誤訊息、套件管理等觀念,對應至 IDE中哪些操作或設定,其它的功能,會在之後說明相關內容時,一併說明 IDE中如果操作或設定。

2.3.2使用了哪個使用了哪個使用了哪個使用了哪個 JRE???? 因為各種原因,你的電腦中可能不只存在一套 JRE!可以試著搜尋電腦中的檔案,例如在Windows中搜尋 java.exe,可能會發現有多個 java.exe檔案,某些程度上,你可以將找到一個 java.exe視作就是有一套 JRE! 在安裝好 JDK後,如果選擇一併安裝 Public JRE,至少會有兩套 JRE存在電腦中,一個是 JDK本身的 Private JRE,一個是選擇安裝的 Public JRE。 既然電腦中有可能同時存在多套 JRE,那麼你到底執行了哪一套 JRE?在文字模式下鍵入 java 指令,如果設定了 PATH,會執行 PATH 順序下找到的第一個第一個第一個第一個 java可執行檔可執行檔可執行檔可執行檔,這個可執行檔所啟動的是哪套 JRE? 當找到 java可執行檔並執行時,會依照以下的規則來尋找可用的 JRE:

� 可否在 java可執行檔資料夾下找到相關原生(Native)程式庫

� 可否在上一層目錄中找到 jre目錄 如果設定 PATH包括 JDK的 bin目錄,執行 java指令時,因為在 JDK的 bin中找不到相關原生程式庫,因此找上一層資料夾的 jre 資料夾中有無原先程式庫,於是找到的是 JDK的 Private JRE。 如果將 PATH設定包括 C:\Program Files\Java\jre7\bin,則執行 java指令時,因為同一資料夾下可以找到相關原生程式庫,於是就使用 C:\Program Files\Java\jre7\這個 Public JRE。

在執行 java指令時,可以附帶一個-version引數,這可以顯示執行的 JRE版本,這是確認所執行 JRE版本的一個方式。例如:

Page 26: Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE

Java SE 7技術手冊草稿

圖圖圖圖 2.32 使用使用使用使用-version確認版本確認版本確認版本確認版本 在剛到一個新開發環境時(例如到客戶那邊去時),先確認版本是很重要的一件事,文字模式下若要確認 JRE,可先檢查 PATH路徑中的順序,再查看 java -version的資訊,這些都是基本的檢查動作。 如果有個需求是切換 JRE,文字模式下必須設定 PATH 順序中,找到的第一個JRE之 bin資料夾是你想要的 JRE,而不是設定 CLASSPATH。

那麼,如果使用 IDE新增專案,你使用了哪個 JRE呢?如果是 NetBeans,會以你安裝時設定的 JDK(參考圖 2.27)中 Private JRE為預設 JRE。在 NetBeans中,如果你想切換所使用的 JDK(JRE),可以如下先新增 Java平台:

1. 執行選單「Tools/Java Platforms」,在出現的「Java Platform Manager」對話方塊中,按下「Add Platform」按鈕。

2. 在出現的對話方塊中,選擇你想要的 JDK目錄,按下「Next>」按鈕。

3. 確認預設的「Platform Name:」、「Platform Sources:」與「Platform Javadoc:」是你想要的設定值後,按下「Finish」完成平台新增。

4. 按下「Java Platform Manager」的「Close」按鈕結束設定。 提示提示提示提示 如果是 Eclipse的話,可以執行選單中「Windows/Preferences」指令,在「Preferences」對話方塊中,選擇「Java/Installed JREs」,進行 JRE版本的新增與新增專案時預設使用的 JRE。

Video

註解註解註解註解: JDK7出來後確認

Page 27: Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE

Java SE 7技術手冊草稿 完成 Java平台新增後,接下來可如下操作,改變專案想使用的 JDK(JRE):

1. 在「Projects」窗格中選擇專案,按右鍵執行「Properties」指令。

2. 在出現的「Project Properties」對話方塊中,選擇「Libraries」,在右邊的「Java

Platform:」選項中,選擇你要使用的 JDK版本後,按下「OK」完成設定。

3. 確認「Projects」窗格中的「Libraries」,已設定為你想要的 JDK版本。

提示提示提示提示 在 Ecl.ipse 中若既有專案要改用別的 JRE,可以於專案上按右鍵,執行「Properties」指令,在出現的「Propertes」對話方塊中,選擇「Java Build

Path」,選擇「Libraries」頁籤中 JRE,按下「Edit...」按鈕,在「Alternate

JRE:」中選擇你要用的 JRE版本。

2.3.3類別檔案類別檔案類別檔案類別檔案版本版本版本版本 如果使用新版本 JDK編譯出位元碼檔案,在舊版本 JRE上執行,有可能會發生以下的錯誤訊息:

Video

Page 28: Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE

Java SE 7技術手冊草稿

圖圖圖圖2.33 不支援此版本位元碼不支援此版本位元碼不支援此版本位元碼不支援此版本位元碼 圖 2.33是在 JDK7下編譯出位元碼,切換 PATH至 JDK6,使用 Private JRE6執行位元碼,結果出現 UnsupportedClassVersionError,並指出這個位元碼的主版本號與次版本號(major.minor)為 51.0。 編譯器會在位元碼檔案中標示主版本號與次版本號,不同的版本號,位元碼檔案格式可能有所不同。JVM 在載入位元碼檔案後,會確認其版本號是否在可接受的範圍,否則就不會處理該位元碼檔案。 可以使用 JDK工具程式 javap,確認位元碼檔案的版本號:

圖圖圖圖 2.34 使用使用使用使用 javap剖析位元碼檔案剖析位元碼檔案剖析位元碼檔案剖析位元碼檔案

Page 29: Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE

Java SE 7技術手冊草稿 可以使 System.getProperty("java.class.version")取得 JRE支援的位元碼版本號.,使用 System.getProperty("java.runtime.version")取得JRE版本訊息。

提示提示提示提示 在 The JavaTM Virtual Machine Specification 中 The class File Format說了了位元碼基本格式:

� http://java.sun.com/docs/books/jvms/second_edition/html/ClassFil

e.doc.html 文件底部的註釋 1中指出,Sun JDK 1.0.2的 JVM實作,支援的位元碼檔案版本號為 45.0到 45.3。1.1.X支援 45.0到 45.65535(向前相容)。Java 2平台支援 45.0到 46.0。Java SE 5與 6支援 49.0到 50.0。Java

SE 7則支援 51.0。

在編譯的時候,可以使用-target 指定編譯出來的位元碼,必須符合指定平台所允許的版本號,使用-source要求編譯器檢查使用的語法不超過指定的版本。例如:

圖圖圖圖 2.35 指定指定指定指定-source與與與與-target選項選項選項選項

上面這個例子指定編譯出來的位元碼檔案必須是 1.6平台可接受的版本號,並檢查使用語法必須是 1.6語法。在不指定-target與-source的情況下,編譯器會有預設的-target 值,例如 JDK7 預設的預設的預設的預設的-target 與與與與-source 都都都都是是是是 1.7,-target 在指定時在指定時在指定時在指定時,,,,值值值值必須大於必須大於必須大於必須大於或等於或等於或等於或等於-source,所以在圖 2.35中,若只指定-target為 1.6,就會無法通過編譯,因為-source仍是預設值 1.7。

提示提示提示提示 JDK7與 JDK6相比,有語法上的新增,所以-source預設為 1.7(-target預設為 1.7)。JDK6(-target預設為 1.6)與 JDK5(-target預設為 1.5)則沒有語法上的新增,所以-source都預設為 1.5。

Page 30: Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE

Java SE 7技術手冊草稿 圖 2.35中可看到,如果只指定-source與-target進行編譯,會出現警示訊息,這是因為編譯時預設的 Bootstrap 類別載入器(Class loader),之後章節會說明Bootstrap類別載入器是什麼。簡單來說,系統預設的類別載入器仍參考至 1.7的 rt.jar(也就是 Java SE 7 API的 JAR檔案),如果引用到一些舊版 JRE沒有的新 API,就會造成在舊版 JRE 上無法執行,最好是編譯時指定-bootclasspath,參考至舊版的rt.jar,這樣在舊版 JRE執行時比較不會發生問題。

事實上,並非一定得切換 PATH至較低版本的 JDK或 JRE,才能測試具較低版本號的類別檔案,如果你已經安裝有舊版 JDK 或 JRE,可以在執行時使用-version引數並指定版本。例如:

圖圖圖圖 2.36 使用使用使用使用-version指定執行版本指定執行版本指定執行版本指定執行版本

圖 2.36 中,第一次編譯時沒有指定版本,也就是使用預設的 1.7 位元碼檔案版本號,執行時指定 1.6版本就出現了 UnsupportedClassVersionError。第二次編譯時指定編譯為 1.6位元碼版本號,執行時指定 1.6版本就沒有問題。

如果使用-version指定的版本,實際上無法在系統上找到已安裝的 JRE,則會出現以下錯誤:

Page 31: Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE

Java SE 7技術手冊草稿

圖圖圖圖 2.37 使用使用使用使用-version指定時無法找到對應版本指定時無法找到對應版本指定時無法找到對應版本指定時無法找到對應版本

那麼在 IDE中如何設定-source與-target對應的選項呢?不同版本 IDE中建立的專案,預設的-source與-target選項並不相同,以 NetBeans 7.0為例,就算使用 JDK7作為平台,預設都是使用 JDK6的-source與-target。如果想改變為 JDK7,可以在專案上按右鍵執行「Properties」指令,在「Sources」中的「Source/Binary Format:」下拉選擇「JDK7」:

圖圖圖圖 2.38 NetBeans中中中中設定設定設定設定 JDK的的的的-source與與與與-target

Page 32: Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE

Java SE 7技術手冊草稿 提示提示提示提示 如果是 Eclipse,則可以在專案上按右鍵執行「Properties」,在「Java

Compiler」中進行設定:

2.4 重重重重點複習點複習點複習點複習 在正式撰寫程式之前,請先確定你可以看到檔案的副檔名。撰寫 Java 程式時有幾點必須注意:

� 副檔名是.java

� 主檔名與類別名稱必須相同

� 注意每個字母大小寫

� 空白只能是半型空白字元或是 Tab字元 一個.java檔案可定義數個類別,但是只能有一個公開(public)類別,而且檔案主檔名必須與公開類別名稱相同。規格書中規定 main()方法的形式一定得是:

public static void main(String[] args) 當你鍵入一個指令而沒有指定路徑資訊時,作業系統會依照 PATH環境變數中設定的路徑順序,依序尋找各路徑下是否有這個指令。若系統中安裝兩個以上 JDK時,Path路徑中設定的順序,將決定執行哪個 JDK下的工具程式,在安裝了多個 JDK或JRE的電腦中,確定執行了哪個版本的 JDK或 JRE非常重要,確定 PATH資訊是一定要作的動作。 在 JVM中執行某個可執行檔(.class),你就要告訴 JVM這個虛擬作業系統到哪些路徑下尋找檔案,方式是透過 CLASSPATH指定其可執行檔(.class)的路徑資訊。在啟動 JVM 時要告知可執行檔(.class)的位置,可以使用-classpath 或-cp 引數來指定。有的時候,希望也從目前資料夾開始尋找類別檔案,則可以使用.指定。

JAR檔案實際使用 ZIP格式壓縮,當中包含一堆.class檔案,設定 CLASSPATH

Page 33: Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE

Java SE 7技術手冊草稿 時可將 JAR檔案當作特別的資料夾。如果某個資料夾中有許多.jar檔案,從 Java SE

6開始,可以使用*表示使用資料夾中所有.jar檔案。 在使用 javac 編譯器時,如果要使用到其它類別程式庫時,也必須使用-cp 指定CLASSPATH,使用-sourcepath 指定尋找原始碼檔案的資料夾,使用-d 指定了編譯完成的位元碼存放資料夾,指定-verbose引數可看到編譯器進行編譯時的過程。 當類別原始碼開始使用 package進行分類時,就會具有四種管理上的意義:

� 原始碼檔案要放置在與 package所定義名稱階層相同的資料夾階層

� package 所定義名稱與 class 所定義名稱,會結合而成類別的完全吻合名稱(Fully qualified name)

� 位元碼檔案要放置在與 package所定義名稱階層相同的資料夾階層

� 要在套件間可以直接使用的類別或方法(Method)必須宣告為 public

import只是偷懶工具,讓你在原始碼中不用使用完全吻合名稱。 當找到 java可執行檔並執行時,會依照以下的規則來尋找可用的 JRE:

� 可否在 java可執行檔資料夾下找到相關原生(Native)程式庫

� 可否在上一層目錄中找到 jre目錄 在執行 java指令時,可以附帶一個-version引數顯示執行的 JRE 版本。在編譯的時候,可以使用-target 指定編譯出來的位元碼,必須符合指定平台所允許的版本號,使用-source要求編譯器檢查使用的語法不超過指定的版本。JDK7預設的-target與-source都是 1.7,-target在指定時,值必須大於或等於-source。