javac把java文件编译成class文件.最简单的应用就是(终端/命令行)进入到java文件所在目录,输入命令
javac myfile.java在当前目录下生成一个myfile.class.或者
javac file1.java file2.java来编译多个java文件.
通过-d参数可以指定class文件生成的目录:
javac -d mydest myfile.java在mydest下生成class文件.
有时要编译的java文件使用到别的文件里定义的类,比如User类里使用了一个别处定义的类Tool:
- /* User.java */
- class User { Tool t = new Tool(); }
- /* Tool.java */
- class Tool {}
如果两个文件在同一个文件夹下,则只需使用命令
javac User.java
就可以编译成功.编译后会生成User.class和Tool.class文件.但如果两个文件不在同一个路径,则需要用-sourcepath参数来指定被引用文件的查找路径:
javac -sourcepath mysrc User.java
这样会在当前路径生成User.class而在mysrc下生成Tool.class.如果此时使用-d参数的话,则两个class文件都会输出到目标路径下.
除了直接引用源文件,还可以引用class文件.比如User.java所在路径下只有Tool.class而不存在Tool.java的话,javac User.java同样会成功.但如果class文件在不同的路径下的话,就需要就-classpath或-cp参数来指明了:
javac -classpath myclass User.java 或 javac -cp myclass User.java
可以从myclass里找到Tool.class.
前面所看到的类都是定义在默认的包中.如果类定义在其它包中的话,事情会稍复杂一些.比如上面两个类的定义为:
- /* User.java */
- package users;
- import tools.Tool;
- class User { Tool t = new Tool(); }
- /* Tool.java */
- package tools;
- public class Tool {}
java里比较bt的一件事就是,package的名字和类文件所在的文夹名必须相同,否则import找不到被引用的包.比如如果一个类定义在a.b.c这个包下面,那么它的类所在的java文件也应该放在名为a/b/c的路径下面.根据上面的代码,如果Tool.java在名为tools的文件夹下的话,直接执行命令javac User.java可以成功. 同样如果tools下只有Tool.class而没有Tool.java的话,编译也是可以通过的.
如果自定义包(比如tools文件夹)并不在当前目录下,就需要通过-sourcepath或-classpath来指定包的位置(不是类文件的位置.即是tools文件夹的位置,而不是Tool.java或Tool.class的位置).
顺带一提,在使用java命令执行一个class文件时,如果自定义包的文件夹或默认包里的类文件不在当前目录下的话,同样需要-classpath来指明class所在的位置,否则会产生找不到类的异常.
Jar用来把多个java类打包成一个可执行的压缩文件。可以用命令java -jar filename.jar来运行一个jar程序。jar也可以作为类库供他人使用,只要把它指定为classpath就可以:javac -cp filename.jar myclass.java以及java -cp filename.jar myclass。
修改上面的代码:
- /* Tool.java */
- package tools;
- public class Tool {
- public void fun() {
- System.out.println("This is a tool!");
- }
- }
- /* User.java */
- package users;
- import tools.*;
- public class User {
- public static void main (String args[]) {
- Tool t = new Tool();
- t.fun();
- }
- }
生成类文件的目录结构如下所示:
-tools
--Tool.class
-users
--User.class
接下来用命令
Jar cf Tommy.jar users/User.class tools/Tool.class可以把User.class和Tool.class打包进一个名为Tommy.jar的jar文件里。参数c表示创建一个新文件,参数f表示下一个参数是生成的jar文件的文件名(即Tommy.jar),之后所有的参数都是要打入进包的文件 。但是这样生成的jar文件不能直接执行,因为jar文件里需要指定一个main class。可以用参数e来指定它:
jar cfe Tommy.jar users/User users/User.class tools/Tool.class
参数fe表示接下来的参数分别是jar文件名和程序入口(即main class),你也可以用ef来改变参数的顺序(即程序入口参数在jar文件名前面)。
在指定了程序入口后,就可以后java -jar Tommy.jar来执行这个jar文件了。默认情况下,java会在jar包的根目录下查找类。比如User.class引用到tools.Tool.class,java就会在tools文件夹下查找Tool.class。但如果把文件目录结构改为:
-lib
--tools
---Tool.class
-users
--User.class
用上面的方式打包后的jar文件在执行时会找不到Tool.class。
除了在命令行中指定程序入口的方式,还可以使用一个manifest文件。它是个文本文件,里面可以这样编辑 :
Main-Class: users/User<回车>
假设这个文本文件名为mymanifest,这样就可以用参数m来指定这个文件:jar cfm Tommy.jar mymanifest users/User.java tools/Tool.java来生成一个程序入口为User的jar文件。
在manifest文件里,还可以指定其它jar文件的路径,比如:
Main-Class: users/User
Class-Path: lib/other.jar lib/third.jar<回车>
因为在运行java -jar时是不能指定classpath的(会被忽略),所以在manifest文件里指定classpath是一种解决方法。注意运行时被引用的jar文件必须存在。
Ant工具可以看作是编译java的make。类似于makefile,在ant执行路径下需要一个名为build.xml的文件。build.xml的根结点必须是project:
- <project name="myproject" />
只要在运行ant时当前目录下有满足上述格式的build.xml就可以得到成功信息。
在project结点下可以放置target结点,在target里可以指定命令:
- <project name="myproject">
- <target name="mytarget">
- <echo message="just test"/>
- </target>
- </project>
执行命令
ant mytarget就会执行mytarget下的命令(ehco打印消息)。
在project里可以设置一个默认的target(default="mytarget">),这样直接运行命令ant就可以启动mytarget下的命令。
project里可以有多个target。而且target可能通过depends属性来表示它与其它target之间的依赖关系(多个路径用逗号隔开):
- <project name="myproject" default="mytarget">
- <target name="mytarget" depends="othertarget">
- <echo message="just test"/>
- </target>
- <target name="othertarget">
- <echo message="execute me first!"/>
- </target>
- </project>
执行ant会先执行othertarget下的命令,接着再执行mytarget的命令。
在project里还可以有property结点。定义的project可以通过${propertyname}来得到值。在target里可以通过if属性来根据某属性是否有定义来决定该target是否要运行。下面是property的例子:
- <project name="myproject" default="mytarget">
- <property name="myproperty" value="myvalue"/>
- <target name="mytarget" depends="othertarget" description="this is my target">
- <echo message="myproperty: ${myproperty}"/>
- </target>
- <target name="othertarget" if="notdefined">
- <echo message="execute me first!"/>
- </target>
- </project>
因为设置了if属性,所以othertarget里的命令不会被执行。和if相对的是unless属性,与if相反,除非unless指定的属性有定义,否则就执行target下的命令。
除了echo,还可以执行其它命令,如copy,move,mkdir,delete:
- <target name="copyfile">
- <copy file="src.txt" tofile="dest.txt"/>
- </target>
- <target name="copyfiletofolder">
- <copy file="src.txt" todir="sub"/>
- </target>
- <target name="copyfolder">
- <copy todir="sub1">
- <fileset dir="sub"/>
- </copy>
- </target>
- <target name="movefile">
- <move file="src.txt" tofile="sub/dest.txt"/>
- </target>
- <target name="makedirectory">
- <mkdir dir="sub"/>
- </target>
- <target name="deletefile">
- <delete file="src.txt"/>
- </target>
- <target name="deletefolder">
- <delete dir="sub1"/>
- </target>
- <target name="deleteclassfiles">
- <delete dir="." includes="**/*.class"/>
- </target>
target可以有一个description属性,没什么用,就是给这个target加些注释。project可以有一个basedir属性,用来指定名命令执行里的基目录。
ant当然也提供了javac和java等命令。下面就把前面的Tool.java和User.java用ant来进行编译打包并执行,我把这两个文件放在名为src的文件夹里:
- <project name="TommyProject" default="compile">
- <target name="clean">
- <delete dir="classes"/>
- </target>
- <target name="buildTool" depends="clean">
- <mkdir dir="classes"/>
- <javac srcdir="src" includes="Tool.java" destdir="classes" includeAntRuntime="false"/>
- </target>
- <target name="buildUser" depends="buildTool">
- <javac srcdir="." includes="src/User.java" destdir="classes" classPath="classes"/>
- </target>
- <target name="compile" depends="buildUser"/>
- <target name="pack" depends="compile">
- <jar basedir="classes" includes="**/*.class" destfile="bin/Tommy.jar">
- <manifest>
- <attribute name="Main-Class" value="users/User"/>
- </manifest>
- </jar>
- </target>
- <target name="run" depends="compile">
- <java classname="users.User" classpath="classes" />
- </target>
- <target name="runjar" depends="pack">
- <java dir="bin" jar="Tommy.jar" fork="true"/>
- </target>
- </project>
上面的build.xml里我提供了javac,java和jar的命令。更多的命令参考,通过丰富的命令列表可以发现ant并不仅仅是用来编译java的。
阅读(1572) | 评论(0) | 转发(0) |