Java程序运行机制及cmd编译运行探究(三) 测试类运行jar包

Java程序运行机制及cmd编译运行探究(三) 测试类运行jar包



Java程序运行机制及cmd编译运行探究(二) cmd编译运行Java程序并打成jar包中,我编写了一个生成随机数的工具类,编译过后,把字节码文件打成了2个jar包,放在d:\jar目录下。randomutil是正常打包,只包含了与class文件中package语句相匹配的文件结构,而randomutil2则把这个文件结构在本地磁盘上的路径也打包了进去。那么这两个jar包有什么区别?怎么使用这个jar包中的类及方法呢?以下,我编写一个测试类,来进行研究。在此过程中,如果遇到cmd命令不明白的,可以参看Java程序运行机制及cmd编译运行探究(一)准备工作






一、编写测试类



//注意这里第一句是import语句,说明要引入其他类,而引入的类的全类名和被引入类的package语句保持一致
import pers.tony.utils.RandomUtils;


public class RandomTest
{
	public static void main(String[] args)
	{
		//调用jar包中随机数的生成方法
		System.out.println(RandomUtils.makeRandom());
	}
}




保存源代码文件,命名为RandomTest.java,存储在d:\testclass目录下,如图所示:




注意代码第一句的import,说明需要引用其他类。



二、编译源代码



进入命令行,先输入正确的命令:javac -classpath d:\jar\randomutil.jar d:\testclass\RandomTest.java






可以看到测试类编译成功。简单解释下这个命令,意思是现在需要编译d:\testclass目录下的RandomTest文件,而编译这个类需要一些其他的类,比如这个类在开头import了一些其他类,那这些被引入的类去哪儿找呢?去d:\jar\randomutil.jar里面找,-classpath参数就是指定了类的搜索路径,如果不指定去哪里搜索这些被引用的类,编译就无法通过,如下图:




注意:

当需要引入的类是在jar包中时,-classpath参数的值一定要写jar包所在的路径加上jar包名,.jar后缀名也要写。


为什么一定要这么写呢?因为我们测试类import语句导入的是pers.tony.utils.RandomUtils的全类名,根据-classpath参数值,它会以d:\jar\randomutil.jar\pers\tony\utils这样的物理路径去找被引用的RandomUtils.class(即classpath的路径+import的路径),如果这里省略了路径或者路径不正确,比如.jar不写,在物理路径下自然找不到RandomUtils.class文件,测试类也就无法编译成功。


题外话:引用jar包中的类,-classpath参数需要把jar包的路径和名字写全,但如果直接引用的是class文件,则-classpath参数写到class文件所在目录就可以了。其实想想也很简单,上面我们写编译命令时classpath值也只写到jar包一层,没有写成javac -classpath d:\jar\randomutil.jar\pers\tony\utils\RandomUtils  d:\testclass\RandomTest.java,因为pers\tony\utils\RandomUtils.class这部分的路径由源代码中的import语句代劳了。



三、运行字节码文件



在测试类编译过程中,由于用到其他类,我们使用-classpath参数指定了程序编译时查找相关类的路径,在运行测试类的时候同样需要指定。输入命令:java -classpath .;d:\jar\randomutil.jar RandomTest,可以看到调用jar包成功。




仔细看-classpath参数,和之前编译时候相比多了一个.;,其中点代表当前路径,分号代表分割符,分割了参数的值。


为什么需要为-classpath参数加上.这个值呢?因为在运行Java程序时,如果指定了-classpath参数,虚拟机会完全按照参数值去寻找当前类的,也就是说如果写成java -classpath d:\jar\randomutil.jar RandomTest,所有要用的类都在d:\jar\randomutil.jar下找,包括RandomTest类,可我们知道RandomTest类不在jar包下,而是当前路径,所以必须加上点。否则我要运行RandomTest类,结果连RandomTest类都找不到,效果如下:




好了,到此解决了jar包的调用问题,然而以上是根据randomutil包进行测试的,那上一篇中的把本地路径一起打成包的randomutil2到底能不能调用呢?


先用randomutil2.jar去编译RandomTest,输入命令javac -classpath d:\jar\randomutil2.jar d:\testclass\RandomTest.java


根据之前得到的结论:虚拟机根据classpath参数的路径+测试类import语句的路径去搜索所有相关类。这样写,虚拟机会以d:\jar\randomutil2.jar\pers\tony\utils目录去搜索RandomUtils.class,但我们知道之前randomutil2打包的时候,根目录是cmdtest,而现在命令中压根没有,这样的话肯定找不到RandomUtils.class,编译肯定过不了,试一下,果然失败!




想一想,上述命令失败的原因是因为寻找类的路径少了个cmdtest目录,那最有可能成功的就是想办法去补全cmdtest这个目录

有两种方法

1. 改命令,在jar包全路径后面加上cmdtest目录

    javac -classpath d:\jar\randomutil2.jar\cmdtest d:\testclass\RandomTest.java


2. 修改源代码中的import语句

    把import pers.tony.utils.RandomUtils;改成import cmdtest.pers.tony.utils.RandomUtils;


 这两种方法至少从表面看,搜索相关类的路径是对的,可结果呢?都不行


比较麻烦就不贴图了,第一种我也不知道为什么,可能规定就是不能写jar包中的目录,可能是引用jar包有某种机制。第二种想一想,我import的是cmdtest.pers.tony.utils.RandomUtils类,可实际上RandomUtils类中的package语句是pers.tony.utils.RandomUtils啊,不匹配所以有问题,可能我的想法有偏差,欢迎指正。可不管怎么说,实际试下来打jar包时要把且只能把和类package语句结构一致的包结构进行打包,否则引用的时候会出现问题。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值