命令行编译Java源文件

众所周知,Java是一门编译型语言,需要编译成字节码才能在JVM上运行。常用的IDE如Eclipse等将编译、运行等步骤结合起来一起执行,只需要按下Run即可完成编译和运行的工作。但是实际上编译java程序的核心是JDK。本文主要讲述了只安装jdk通过命令行来编译运行Java程序。

JDK 与 JRE

说到JDK和JRE的关系。可以简单认为JDK是用来编译java文件的,而jre是用来运行编译生成的class文件。JDK中包含JRE,在JDK的安装目录下有一个名为jre的目录,里面有两个文件夹bin和lib,在这里可以认为bin里的就是jvm,lib中则是jvm工作所需要的类库,而jvm和 lib和起来就称为jre。

另外在windows下安装jdk是会有选择是否安装单独的jre,如果选择安装,那么就会安装了两套jre,一套包含在jdk安装目录中,另外一套则是独立安装的jre。那么这两套jre有区别吗

答案是有的,因为jdk是作为开发使用的,而jre仅仅是作为运行java程序的环境。因此具备开发功能的jdk自己的jre下会同时有client性质的jvm和server性质的 jvm,而仅仅作为运行环境的jre下只需要client性质的jvm.dll就够了。

可根据需要编译的源文件的数目和位置将通过命令行编译运行java程序分成两大类。一类是只有单一的源文件,另外一种是有多个源文件。

单个源文件

单个原文件是最简单的了,编译命令为: javac source.java 运行的命令为 java source 上面没有考虑单个源文件中引入的jar包,假如引入了不在classpath环境变量中的jar包时,需要在编译时加上-classpath参数。即命令为: javac -classpath *.jar source.java

多个源文件

编译多个源文件是指其中一个源文件引用了另外一个源文件里面的类。这里可以根据源文件是否在同一个包进行以下分类。

源文件在同一个包

这时候只需要编译“最顶层”的类的源文件即可,比如说有以下三个类:

类E源文件如下

1
2
3
4
5
public class E{
public E(){
System.out.println("this is E");
}
}

类C源文件如下

1
2
3
4
5
6
public  class C{
public C(){
E e=new E();
System.out.println("this is C");
}
}

类D源文件如下

1
2
3
4
5
6
public class D{
public static void main(String [] args){
C c=new C();
System.out.println("this is D");
}
}
现在这三个源文件在同一个包,也就是同一个文件夹下,此时只需要编译类D的源文件即可,执行时也只需要执行类D的class文件。即依次执行下面命令

1
2
javac D.java
java D

得到的结果如下:

1
2
3
this is E
this is C
this is D

源文件不在同一个包

这种情况下又可分为两种情况,详见下面例子

第一种情况:

类B的源文件如下:

1
2
3
4
5
6
7
8
package tcp;

public class B{
public B(){
System.out.println("this is B");
}

}

类A的源文件如下:

1
2
3
4
5
6
7
8
import tcp.*;

public class A{
public static void main(String [] args){
B b=new B();
System.out.println("this is A");
}
}
这时候需要建立一个名为tcp的目录,将类B的源文件放到tcp目录中,然后类A的源文件与tcp目录在同一个目录下,这时候只需要进入到类A所在目录下执行javac A.java即可生成A.classB.class两个类文件,且B.class在tcp目录下生成。再执行命令java A便可得到以下结果:

1
2
this is B
this is A

第二种情况

在第一种情况下类A并没有在任何包中,那么假如类A也在一个包中该怎么编译运行呢?

在类A的源文件的开头添加多一行pacakge udp;即类A在包udp中,这时候通过命令行该怎么编译?

首先建立tcpudp两个文件夹且将他们放在同一目录,tcp目录中放置B.java,udp目录中放置A.java,编译的方法有两种:

第一种:进入到udp目录,执行命令javac -classpath .. A.java 第二种:不进入tcp或udp,在tcp和udp所在的目录执行命令javac udp\A.java

第一种方法的-classpath参数指出了tcp包所在目录,..表示上一层目录,这里采用了相对路径,也可采用绝对路径。

第二种方法利用了jdk编译时遇到import的包时会先在当前目录寻找的特性。

执行A程序的步骤则只有一种方法,就是在tcp和udp目录下执行命令 java udp.A