建立和運行Java代碼
爲了對這篇文章進行更具體的討論,我將使用一些非常簡單的Java類,在同一個包中通過彼此相關的組合或繼承(不在 未命名的包中)來調用dustin.examples
。這兩個在第三個類之前是沒有 main
函數的,直到 Main.java
纔有 main
函數爲了在沒有IDE的情況下運行示例。三個類的代碼清單如下。
Parent.java
1
2
3
4
5
6
7
8
9
10
|
package
dustin.examples; public
class
Parent { @Override public
String toString() { return
"I'm the Parent." ; } } |
Child.java
1
2
3
4
5
6
7
8
9
10
|
package
dustin.examples; public
class
Child extends
Parent { @Override public
String toString() { return
"I'm the Child." ; } } |
Main.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
package
dustin.examples; import
static
java.lang.System.out; public
class
Main { private
final
Parent parent = new
Parent(); private
final
Child child = new
Child(); public
static
void
main( final
String[] arguments) { final
Main instance = new
Main(); out.println(instance.parent); out.println(instance.child); } } |
接下來顯示了目錄結構與這些類的 .java
源文件。截圖顯示源文件的目錄層次結構代表了包名(dustin/examples
源自包 dustin.examples
)和該子目錄下被稱爲package-reflecting的目錄層次結構 src
。我還創建了 classes
子目錄(當前爲空)用於存放編譯後文件 .class
文件,因爲 javac
在目錄不存在的情況下不會創建該目錄。
用javac構建和運行java
無論使用哪種方法正常地構建Java代碼(Ant, Maven, Gradle, 或者 IDE),我相信謹慎的做法是,至少了解如何使用 javac來構建Java代碼。Oracle/Sun的支持者們使用 javac 命令行工具的基本項來運行, javac
-help
也可以運行 javac -help -X
來查看其它的擴展選項。如何應用這些選項的更多細節可以在 Windows 或者 Unix/Linux的javac
的文檔工具查看。
當進入 javac
文檔 時, -sourcepath
選項可以被用來表示源文件存在的路徑。在上面所呈現的目錄結構中,假設我在運行 C:\java\examples\javacAndJava\
目錄的 javac
命令,這將意味着會需要這樣的命令: javac
-sourcepath src src\dustin\examples\*.java
。下一張截圖顯示了結果。
因爲我們沒有指定 .class
文件的目標目錄,在默認情況下它們被放置在同一個目錄下被編譯的 .java
源文件。我們可以使用 -d
選項來糾正這種情況。我們現在可以運行的命令,例如 javac
-sourcepath src -d classes src\dustin\examples\*.java
。如前所述,指定目標目錄(classes
)必須是存在的。這樣,命令將會在下面的截圖指定的目錄下定位.class文件。
用Java源文件編譯成適當的 .class
文件在指定的目錄中,我們現在可以運行Java應用程序啓動命令行工具 java。這僅僅是通過by java
-help
所示的指令或者是 java工具頁 和.class
文件的 -classpath
所指定的地方(或 -cp
)選項。使用兩種方法來指定 classes
目錄以便用於找到 .class
文件,接下來的截圖印證了這點。最後一個參數是完全合格的(整個Java包)類名,它有一個 main
函數來執行。下面的截圖顯示了java
-cp classes dustin.examples.Main
和java -classpath classes dustin.examples.Main
的命令。
構建和運行Ant
對於最簡單的Java應用程序, javac
and java
使用起來非常簡單,它們用於構建並執行應用程序就分別證明了這一點。應用程序會稍微複雜一點(如代碼中存在多個包/目錄或更復雜的依賴於第三方庫和框架的類路徑),但這種方法非常難用。 Apache
Ant 是最古老的“三巨頭”,它是被用於成千上萬的應用程序部署的Java構建工具。正如我討論過 以前的一篇博客,一個基礎的Ant構建文件很容易被創建,特別是如果都始於一個模板就像我在 這篇文章中介紹的一樣。
接下來的代碼是Ant的 build.xml
文件的,它將 .java
文件
編譯成 .class
文件然後運行 dustin.examples.Main
類就像上面的 javac
和 java
一樣。
build.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
<? xml
version = "1.0"
encoding = "UTF-8" ?> < project
name = "BuildingSansIDE"
default = "run"
basedir = "." > < description >Building
Simple Java Applications Without An IDE</ description > < target
name = "compile" description = "Compile
the Java code." > < javac
srcdir = "src" destdir = "classes" debug = "true" includeantruntime = "false"
/> </ target > < target
name = "run"
depends = "compile" description = "Run
the Java application." > < java
classname = "dustin.examples.Main"
fork = "true" > < classpath > < pathelement
path = "classes" /> </ classpath > </ java > </ target > </ project > |
我沒有使用Ant也沒有包括一般所用的方式(例如 “clean” 和 “javadoc”),我使用的是 javac
和 java
來使例子儘可能的簡單。請注意我使用了”debug”來給javac
Ant 任務設置”true”;因爲這不是Ant的默認方式而是javac的默認方式。的確,Ant的 javac
task 和 java task與 javac
and java
的命令工具非常相似。
因爲我希望使用默認名稱Ant來構建文件的時候不顯式指定(build.xml
),因爲我提供“運行”的目標,構建文件的“默認形式”,因爲“編譯”作爲一個依賴包括“運行”的目標,此外Ant是我的環境路徑,我所需要做的是在命令行上讓Ant來編譯運行目錄下的“ant”類型的 build.xml
文件示例,下圖就印證了這一點。
雖然我演示了用Ant編譯和運行一個簡單的Java應用程序,通常我只用Ant進行編譯同時用java
來運行(或者如果classpath非常複雜時就使用 java
腳本來執行)。
用Maven來搭建和運行
雖然Ant是第一個主流的Java構建工具, Apache Maven 最終獲得了成功在很大程度上要感謝它採用的配置是按照慣例同時也支持常見的庫。當代碼和生成的 標準目錄佈局對象一致時,Maven很容易使用。很遺憾,我的例子不遵循這個目錄結構,但Maven允許我 覆蓋默認的目錄結構。下面的Maven POM文件覆蓋了源代碼和目標目錄以及提供了一個Maven構建所需的最小元素,此時Maven的版本是Maven 3.2.1。
pom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
|
< project > < modelVersion >4.0.0</ modelVersion > < groupId >dustin.examples</ groupId > < artifactId >CompilingAndRunningWithoutIDE</ artifactId > < version >1</ version > < build > < defaultGoal >compile</ defaultGoal > < sourceDirectory >src</ sourceDirectory > < outputDirectory >classes</ outputDirectory > < finalName >${project.artifactId}-${project.version}</ finalName > </ build > </ project > |
因爲上面的 pom.xml
文件指定了一個“compile”的“defaultGoal”, pom.xml
是默認定義的POM文件,用執行器(mvn)來搜索,因爲Maven安裝的 bin
文件夾在我的path環境變量中,我只需要運行“mvn”來編譯 .class
文件,這在下張截圖中將會顯示。
我也可以用Maven的 mvn exec:java -Dexec.mainClass=dustin.examples.Main
命令來運行編譯後的應用程序,下圖得以展示。
與Ant一樣,我通常不使用Maven運行簡單的Java應用程序,而是用 java
運行編譯後的代碼(或者使用腳本直接調用 java
的classpath路徑)。
用Gradle構建和運行
Gradle 是最新,最流行和最時尚的三大主流Java構建工具之一。我有時會懷疑時髦東西的本質,但是我發現了有不少東西 例如Gradle (用Groovy編寫的XML, 內置Ant支持和Ivy支持,配置按照慣例很容易被覆蓋,Maven存儲庫支持等)。下一個例子顯示了一個Gradle構建文件,它可用於編譯和運行一個簡單的應用程序,這裏主要展示一下示例代碼。它改編自我在博客 簡單Gradle Java插件定義的例子。
build.gradle
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
apply
plugin: 'java' apply
plugin: 'application' //
Redefine where Gradle should expect Java source files (*.java) sourceSets
{ main
{ java
{ srcDirs
'src' } } } //
Redefine where .class files are written sourceSets.main.output.classesDir
= file("classes") //
Specify main class to be executed mainClassName
= "dustin.examples.Main" defaultTasks
'compileJava', 'run' |
前兩行 build.gradle
文件指定 Java
plugin 和 Application
plugin的應用程序,它將許多功能自動構建。“sourceSets” 和 “sourceSets.main.output.classesDir”的定義允許覆蓋Gradle’s Java 插件各自的Java源代碼和編譯文件類的默認目錄。“mainClassName”明確了規範類應該作爲應用程序的一部分插件運行。“defaultTasks”指定要運行的任務,只需在命令行鍵入:‘compileJava’是一個標準的提供任務的Java插件,‘run’是一個標準的提供任務的應用程序的插件。因爲我稱構建文件爲 build.gradle
,因爲我指定默認的‘compileJava’任務和‘run’
方式,因爲我有Gradle的 bin
文件夾安裝目錄,我需要做的就是構建和運行示例來 鍵入“gradle”命令,接下來將得到證實。
甚至最大的懷疑者都承認Gradle構建對於這個簡單示例都非常方便。它的某些約定和假設結合了簡潔的依賴,很容易根據需要重寫選擇違約的機制。這一事實,這在Groovy而不是XML中也非常吸引人!
Ant和Maven一樣,我傾向於只用這些工具,通過 java
或者腳本調用 java
來直接構建和運行編譯好的 .class
文件。順便說一下,我通常也保存這些 .class
文件爲JAR來運行,但這超出了本文的範圍。
總結
IDE通常沒有必要構建簡單的應用程序和例子,它的開銷甚至比最簡單的例子都要多,這時直接使用 javac
和 java
來構建和運行實例就顯得非常方便。爲了使Ant,Maven或者Gradle的構建工具變得更加有吸引力,許多IDE支持着這些構件工具,這意味着開發者要將構件工具轉移到IDE上,如果已經確定了先前創建的過程,那麼IDE支持的簡單應用就已經成長爲了一個成熟的項目。