Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1800324
  • 博文数量: 438
  • 博客积分: 9799
  • 博客等级: 中将
  • 技术积分: 6092
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-25 17:25
文章分类

全部博文(438)

文章存档

2019年(1)

2013年(8)

2012年(429)

分类: LINUX

2012-03-26 18:09:06

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:


  1. /* User.java */
  2. class User { Tool t = new Tool(); }

  3. /* Tool.java */
  4. 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.

前面所看到的类都是定义在默认的包中.如果类定义在其它包中的话,事情会稍复杂一些.比如上面两个类的定义为:


  1. /* User.java */
  2. package users;
  3. import tools.Tool;
  4. class User { Tool t = new Tool(); }

  5. /* Tool.java */
  6. package tools;
  7. 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

修改上面的代码:


  1. /* Tool.java */
  2. package tools;
  3. public class Tool {
  4.     public void fun() {
  5.         System.out.println("This is a tool!");
  6.     }
  7. }

  8. /* User.java */
  9. package users;
  10. import tools.*;
  11. public class User {
  12.     public static void main (String args[]) {
  13.         Tool t = new Tool();
  14.         t.fun();
  15.     }
  16. }

生成类文件的目录结构如下所示:
-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:


  1. <project name="myproject" />

只要在运行ant时当前目录下有满足上述格式的build.xml就可以得到成功信息。

在project结点下可以放置target结点,在target里可以指定命令:

  1. <project name="myproject">
  2.   <target name="mytarget">
  3.     <echo message="just test"/>
  4.   </target>
  5. </project>

执行命令ant mytarget就会执行mytarget下的命令(ehco打印消息)。

在project里可以设置一个默认的target(default="mytarget">),这样直接运行命令ant就可以启动mytarget下的命令。

project里可以有多个target。而且target可能通过depends属性来表示它与其它target之间的依赖关系(多个路径用逗号隔开):


  1. <project name="myproject" default="mytarget">
  2.   <target name="mytarget" depends="othertarget">
  3.     <echo message="just test"/>
  4.   </target>
  5.   <target name="othertarget">
  6.     <echo message="execute me first!"/>
  7.   </target>
  8. </project>

执行ant会先执行othertarget下的命令,接着再执行mytarget的命令。

在project里还可以有property结点。定义的project可以通过${propertyname}来得到值。在target里可以通过if属性来根据某属性是否有定义来决定该target是否要运行。下面是property的例子:


  1. <project name="myproject" default="mytarget">
  2.   <property name="myproperty" value="myvalue"/>
  3.   <target name="mytarget" depends="othertarget" description="this is my target">
  4.     <echo message="myproperty: ${myproperty}"/>
  5.   </target>
  6.   <target name="othertarget" if="notdefined">
  7.     <echo message="execute me first!"/>
  8.   </target>
  9. </project>

因为设置了if属性,所以othertarget里的命令不会被执行。和if相对的是unless属性,与if相反,除非unless指定的属性有定义,否则就执行target下的命令。

除了echo,还可以执行其它命令,如copy,move,mkdir,delete:


  1. <target name="copyfile">
  2.     <copy file="src.txt" tofile="dest.txt"/>
  3.   </target>
  4.   <target name="copyfiletofolder">
  5.     <copy file="src.txt" todir="sub"/>
  6.   </target>
  7.   <target name="copyfolder">
  8.     <copy todir="sub1">
  9.       <fileset dir="sub"/>
  10.     </copy>
  11.   </target>
  12.   <target name="movefile">
  13.     <move file="src.txt" tofile="sub/dest.txt"/>
  14.   </target>
  15.   <target name="makedirectory">
  16.     <mkdir dir="sub"/>
  17.   </target>
  18.   <target name="deletefile">
  19.     <delete file="src.txt"/>
  20.   </target>
  21.   <target name="deletefolder">
  22.     <delete dir="sub1"/>
  23.   </target>
  24.   <target name="deleteclassfiles">
  25.     <delete dir="." includes="**/*.class"/>
  26.   </target>

target可以有一个description属性,没什么用,就是给这个target加些注释。project可以有一个basedir属性,用来指定名命令执行里的基目录。

ant当然也提供了javac和java等命令。下面就把前面的Tool.java和User.java用ant来进行编译打包并执行,我把这两个文件放在名为src的文件夹里:


  1. <project name="TommyProject" default="compile">
  2.   <target name="clean">
  3.     <delete dir="classes"/>
  4.   </target>
  5.   <target name="buildTool" depends="clean">
  6.     <mkdir dir="classes"/>
  7.     <javac srcdir="src" includes="Tool.java" destdir="classes" includeAntRuntime="false"/>
  8.   </target>
  9.   <target name="buildUser" depends="buildTool">
  10.     <javac srcdir="." includes="src/User.java" destdir="classes" classPath="classes"/>
  11.   </target>
  12.   <target name="compile" depends="buildUser"/>
  13.   <target name="pack" depends="compile">
  14.     <jar basedir="classes" includes="**/*.class" destfile="bin/Tommy.jar">
  15.       <manifest>
  16.         <attribute name="Main-Class" value="users/User"/>
  17.       </manifest>
  18.     </jar>
  19.   </target>
  20.   <target name="run" depends="compile">
  21.     <java classname="users.User" classpath="classes" />
  22.   </target>
  23.   <target name="runjar" depends="pack">
  24.     <java dir="bin" jar="Tommy.jar" fork="true"/>
  25.   </target>
  26. </project>

上面的build.xml里我提供了javac,java和jar的命令。更多的命令参考,通过丰富的命令列表可以发现ant并不仅仅是用来编译java的。



阅读(1572) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~