來解決原始碼檔案與位元碼檔案都放在一起的問題。請將 JavaGossip / Labs / SOURCEPATH-javac / 的Hello1資料夾複製至C:\workspace中,Hello1資料夾中有src與classes資料夾,src資料夾中有Console.java與Main.java兩個檔案,其中Console.java就是 編譯器與 CLASSPATH 中Console
類別的原始碼(目前你不用關心它如何撰寫),而Main.java的內容 編譯器與 CLASSPATH 中的Main.java相同。
src資料夾將用來放置原始碼檔案,而編譯好的位元碼檔案,希望能指定存放至classes資料夾。你可以在文字模式下,切換至Hello1資料夾,然後如下進行編譯:
在編譯src/Main.java時,由於程式碼中要使用到
Console
類別,你必須告訴編譯器,Console
類別的原始碼檔案存放位置,這邊使用-sourcepath
指定從src資料夾中尋找原始碼檔案,而-d
指定了編譯完成的位元碼存放資料夾,編譯器會將使用到的相關類別原始碼也一併進行編譯,編譯完成後,會在classes資料夾中看到Console.class與Main.class檔案。你可以如下執行程式:你可以在編譯時指定
-verbose
引數,看到編譯器進行編譯時的過程,這有助於了解SOURCEPATH
與CLASSPATH
的差別,目前要瞭解的部份有 …[parsing started RegularFileObject[src\Main.java]]
[parsing completed 32ms]
[search path for source files: src]
[search path for class files: C:\Program Files\Java\jdk1.8.0\jre\lib\resources.j
ar,C:\Program Files\Java\jdk1.8.0\jre\lib\rt.jar,C:\Program Files\Java\jdk1.8.0\
jre\lib\sunrsasign.jar,C:\Program Files\Java\jdk1.8.0\jre\lib\jsse.jar,C:\Progra
m Files\Java\jdk1.8.0\jre\lib\jce.jar,C:\Program Files\Java\jdk1.8.0\jre\lib\cha
rsets.jar,C:\Program Files\Java\jdk1.8.0\jre\lib\jfr.jar,C:\Program Files\Java\j
dk1.8.0\jre\classes,C:\Program Files\Java\jdk1.8.0\jre\lib\ext\access-bridge-64.
jar,C:\Program Files\Java\jdk1.8.0\jre\lib\ext\cldrdata.jar,C:\Program Files\Jav
a\jdk1.8.0\jre\lib\ext\dnsns.jar,C:\Program Files\Java\jdk1.8.0\jre\lib\ext\jacc
ess.jar,C:\Program Files\Java\jdk1.8.0\jre\lib\ext\jfxrt.jar,C:\Program Files\Ja
va\jdk1.8.0\jre\lib\ext\localedata.jar,C:\Program Files\Java\jdk1.8.0\jre\lib\ex
t\nashorn.jar,C:\Program Files\Java\jdk1.8.0\jre\lib\ext\sunec.jar,C:\Program Fi
les\Java\jdk1.8.0\jre\lib\ext\sunjce_provider.jar,C:\Program Files\Java\jdk1.8.0
\jre\lib\ext\sunmscapi.jar,C:\Program Files\Java\jdk1.8.0\jre\lib\ext\sunpkcs11.
jar,C:\Program Files\Java\jdk1.8.0\jre\lib\ext\zipfs.jar,.]
...
[wrote RegularFileObject[classes\Main.class]]
[checking Console]
...
[wrote RegularFileObject[classes\Console.class]]
[total 781ms]
在編譯時,會先搜尋-sourcepath
指定的資料夾(上例指定src)是不是有使用到的類別原始碼,然後會搜尋CLASSPATH
中,是否有已編譯的類別位元碼,你可以發現,其實預設搜尋位元碼的路徑包括許多預設的JAR檔案,像是rt.jar等,留意最後那那個「.
」,由於沒有指定-classpath
(-cp
),預設會搜尋目前路徑。
確認原始碼與位元碼搜尋路徑之後,接著檢查CLASSPATH
中是否已經有編譯完成的Main
類別,如果存在且從上次編譯後,Main
類別的原始碼並沒有改變,則無需重新編譯,如果不存在,則重新編譯Main
類別,就上例而言,由於CLASSPATH
並不包括classes資料夾,所以找不到Main
類別位元碼,因此重新編譯出Main.class並存放至classes中。
接著檢查CLASSPAT
H中是否已經有編譯完成的Console
類別,如果存在且從上次編譯後,Console
類別的原始碼並沒有改變,則無需重新編譯,如果不存在,則重新編譯Console
類別,就上例而言,由於CLASSPATH
並不包括classes資料夾,所以找不到Console
類別位元碼,因此重新編譯出Console.class並存放至classes中。
實際專案中會有數以萬計的類別,如果每次都要重新將.java編譯為.class,那會是非常費時的工作,所以編譯時若類別路徑中已存在位元碼,且上次編譯後,原始碼並沒有修改,無需重新編譯會比較節省時間,因此,就上例而言,應該指定-cp
為classes。例如:
[parsing started RegularFileObject[src\Main.java]]
[parsing completed 32ms]
[search path for source files: src]
[search path for class files: C:\Program Files\Java\jdk1.8.0\jre\lib\resources.j
ar,C:\Program Files\Java\jdk1.8.0\jre\lib\rt.jar,C:\Program Files\Java\jdk1.8.0\
jre\lib\sunrsasign.jar,C:\Program Files\Java\jdk1.8.0\jre\lib\jsse.jar,C:\Progra
m Files\Java\jdk1.8.0\jre\lib\jce.jar,C:\Program Files\Java\jdk1.8.0\jre\lib\cha
rsets.jar,C:\Program Files\Java\jdk1.8.0\jre\lib\jfr.jar,C:\Program Files\Java\j
dk1.8.0\jre\classes,C:\Program Files\Java\jdk1.8.0\jre\lib\ext\access-bridge-64.
jar,C:\Program Files\Java\jdk1.8.0\jre\lib\ext\cldrdata.jar,C:\Program Files\Jav
a\jdk1.8.0\jre\lib\ext\dnsns.jar,C:\Program Files\Java\jdk1.8.0\jre\lib\ext\jacc
ess.jar,C:\Program Files\Java\jdk1.8.0\jre\lib\ext\jfxrt.jar,C:\Program Files\Ja
va\jdk1.8.0\jre\lib\ext\localedata.jar,C:\Program Files\Java\jdk1.8.0\jre\lib\ex
t\nashorn.jar,C:\Program Files\Java\jdk1.8.0\jre\lib\ext\sunec.jar,C:\Program Fi
les\Java\jdk1.8.0\jre\lib\ext\sunjce_provider.jar,C:\Program Files\Java\jdk1.8.0
\jre\lib\ext\sunmscapi.jar,C:\Program Files\Java\jdk1.8.0\jre\lib\ext\sunpkcs11.
jar,C:\Program Files\Java\jdk1.8.0\jre\lib\ext\zipfs.jar,classes]
...
[loading RegularFileObject[classes\Console.class]]
[wrote RegularFileObject[classes\Main.class]]
[total 687ms]
這次指定了
-sourcepath
為src,而-cp
為classes,所以會在src中搜尋位原始碼檔案,在classes中搜尋位元碼檔案(注意最後的classes),由於CLASSPATH
中包括classes資料夾,所以找到Console
類別位元碼,因此無需重新編譯Console.class,而只編譯javac
指定的Main.java為Main.class。