目标:写一个RandomUtils.java工具类,返回一个随机数,并把这个类的字节码文件打成jar包
在Java运行机制及cmd编译运行探究(一)准备工作一文中,我总结了一部分要用到的cmd及编译运行的命令,如果在本文对命令有所疑问,请移步参阅
1. 编写工具类源代码并保存
代码:
package pers.tony.utils;
public class RandomUtils {
/**
* 生成随机数
*/
public static String makeRandom()
{
int a = (int)(Math.random()*10+1);
return "返回1~10随机数:"+a;
}
public static void main(String[] args)
{
System.out.println(makeRandom());
}
}
很简单的一个打印1~10随机数的程序,我用的记事本,也可以是其他文字编辑软件。保存好代码,文件命名为RandomUtils.java,文件存在
我本地的位置
为D:\cmdtest,效果如下:
注意:
1. 如果Java源文件中有public类,则文件名字一定要和public类的名字一样,如果没有,理论上可以取任何名字。
2. 注意观察cmdtest目录,此时只有一个RandomUtils.java文件
2. 编译工具类源代码,获得字节码文件
win+R,输入cmd,打开命令行,输入命令javac -d d:/cmdtest d:\cmdtest\RandomUtils.java
按下回车,看到在D:\cmdtest\pers\tony\utils目录下生成了RandomUtils的字节码文件
注意:
1. 编译位于包中的类,编译时要带上-d可选参数
注意观察cmdtest目录,相比编译前,依次多了pers,tony,utils文件夹,而RandomUtils的字节码文件放在utils下
我们知道Java通过引入包机制来区分同名的类,Java同时规定位于包中的类,在文件系统中也必须有与包名层次相同的目录结构
仔细看RandomUtils类源代码,它是放在一个名叫pers.tony.utils包下。编译这种位于包中的类,我们用javac命令进行编译的时候一定要加上-d的可选参数,如果不加,就无法生成一个带层次的目录结构。
来验证一下:
输入命令:javac d:\cmdtest\RandomUtils.java
效果如下:
如果不带-d参数的话,生成的字节码文件直接放在了同java文件一块儿的目录下,确实没有生成文件系统下的目录结构。而第一个pers文件夹是刚才用带-d参数的命令生成的。现在一个是带包目录结构的,一个是不带包目录结构的,两个字节码运行时候有什么差别呢?
3. 运行工具类字节码
我们先以不正确方式生成的字节码文件进行运行测试,进入字节码文件所在目录,使用命令java RandomUtils
哈哈,好像不行呢,那再看看刚刚以正确方式生成的字节码文件表现如何
进入字节码文件所在目录,使用命令java pers.tony.utils.RandomUtils
成功了,返回了一个随机数8,那么为什么会这样呢?前面提到了Java规定文件系统的目录结构要一致,而RandomUtils.java放在了per.tony.utils包下,如果目录结构不对,是无法运行的,这里的实际运行结果是个佐证,其次注意这里运行位于包中类的运行方式,是在类所在包的根目录下运行java+空格+全类名。
4. 对字节码文件进行打包
jdk中自带了一个jar命令可以用于在cmd中打包,如果不知道怎么用可以在命令行中输入“jar”,可以查看各种命令参数和示例。
先进入cmdtest目录,再执行jar cvf d:\jar\randomutil.jar pers\tony\utils\RandomUtils.class生成jar包,意思是把当前目录下pers\tony\utils\RandomUtils.class按原有物理文件结构打成jar包,存在d:\jar目录下,jar包的名字是randomutils,其中cvf是参数,c代表创建新档案,v代表生成详细输出,f代表指定档案文件名。
生成效果如下:
jar包是生成了,可是结构对不对呢?我用WinRAR打开,如下图:
对比一下,在randomutil的jar包里面,RandomUtils的字节码文件的包结构是符合之前提到的Java规定的(即类中第一句的package语句的包结构和实际文件系统的层次结构一致)。
前面说要先进cmdtest目录,为什么呢?试试如果直接在外面打jar包会怎么样。
打开命令行,直接输入jar cvf d:\jar\randomutil2.jar d:\cmdtest\pers\tony\utils\RandomUtils.class,执行命令,我们会发现也能打包成功,可是用WinRAR打开就会发现不同
可以看到jar包里面最外层套了个cmd文件夹,由此可知在jar cvf A B这个命令中,它会把B中的完整目录结构打包到A。事实上我们需要打包的其实只有类的字节码文件及与其package语句相对应的文件包结构(即pers\tony\utils\RandomUtils.class结构),不需要把它在本地磁盘上的路径(cmdtest目录)也打包进去,更重要的是打jar包的目的是为了使用jar包,如果把无关的目录给打包进去,在使用jar包的时候会出现问题,这一点将在下一篇如何使用jar包会进行讨论。
至此,cmd下打jar包的工作告一段落。