jar : java archive, 是对java的类文件/目录 的存档压缩文件, 跟zip的压缩格式完全相同
是为了将你写的java类(主要是通用类/工具类) 提供给其他外部 程序使用
跟package的作用是基本一样的, 只是 package是未被压缩的 类的集合包, 而jar是对package包的 再压缩, 是对类的集合包的一个压缩. 所以, 对jar文件的作用和使用方法跟package是一样的, 通常package是放在当前应用程序中,被本程序中的其他类使用, 这个当然不用压缩打包了. 而jar通常是放在 其他应用程序中 , 被其他人/其他应用程序而使用
jar文件 既可以 直接运行( jar中包含的主类的main函数就是入口点 entry point), 也可以 让其中包含的非主类的非main方法等 被其他外部程序使用. 为了方便其他程序中直接使用jar 文件中的类的方法, 通常是将jar中的类, 定义为public, 而且将其中类包含的方法 定义为public static, 这样就直接通过类名来引用方法, 不需要再去创建一个类对象了
?? 首先是如何创建一个jar文件 (注意, jar是一个文件, 不是一个包, 所以叫 jar文件,不是jar包)
运用jar命令: jar cvfm utilCMOS.jar util.mf -C ~/util
这是一个bsd风格的jar命令, -c是创建(还有-x, -t, -u等), -v verbos, -f指定jar包文件名, -m指定m清单anifest.mf的名字. -C 指定归档源文件目录, 如果不指定目录, 就可以直接指定归档的(多个) 类文件: jar cvf utilCMOS.jar utilCMOSRead.class utilCMOSRewrite.class
?? 运行jar文件
运行jar文件(中的主类) 的方法是: java -jar xxx.jar
java执行的对象可以是 类文件和 jar文件 两种, 一种是execute a class, 一种是 to execute a jar file
[lae@localhost ~]$ java
Usage: java [-options] class [args...]
(to execute a class)
or java [-options] -jar jarfile [args...]
(to execute a jar file)
?? 引用jar文件中的某个类
如果要使用里面的具体某个类,这时可以通过: java -cp xxx.jar xxx.com.xxxx
注意, java命令支持的就是 X toolkit风格的选项!
**其中-cp命令是将xxx.jar加入到classpath,这样java class loader就会在这里面查找匹配的类。 **
======================================================
?Linux命令行引用jar包
一般情况下:如果java 文件和jar 包在同一目录 poi-3.0-alpha3-20061212.jar 和testTwo.java
编译:javac -cp poi-3.0-alpha3-20061212.jar:. testTwo.java
执行:java -cp poi-3.0-alpha3-20061212.jar:. testTwo
如果java文件和jar包不在同一目录 ~/poi-3.0-alpha3-20061212.jar ./testTwo.java
编译:javac -cp ~/poi-3.0-alpha3-20061212.jar:. ./testTwo.java
执行:java -cp ~/poi-3.0-alpha3-20061212.jar:. testTwo
当要引用多个jar包时:
假设有个程序的启动方法在test.java里, 运行Java程序是java test,
但是如果要引用其他jar包, 使用java -classpath xx.jar xx2.jar xx3.jar ... test
但是jar很多的话,就要一个一个写上去,非常麻烦, 而且jar文件的名称和内容 可能经常变
那么, 可以将要引用的 多个jar 文件统一的放在一个文件夹中, 比如放在lib文件夹中:java -Djava.ext.dirs=lib test
………………
jar文件(有时也叫jar包) 就是Java类包,只不过是打包了而已
所以在程序中引用jar 包中的类方法,跟引用package 包 类的方法是一样的
只是在编译Java文件 和执行类的时候,要指明 -cp 选项
这样通过命令行的方式, 就知道了 程序中,要引用/使用 "外来的包/外部包/下载的别人的包" 中的类时, 是如何使用的方法和思想: 就是通过 -cp 选项或 -Djava.ext.dirs=lib 这样的选项来 告诉java 类载入器loader去查找类的路径. 这个在c++程序中也是一样的方法和思想, 在ide中通过图形界面菜单和选项来指定引用类/包/jar文件等 其实质和最终结果都是一样的,只是命令行更简单直接! ide图形界面还要麻烦些!!
=============================
mv命令可以用来更名或 移动(剪切)
移动时, 可以同时 移动多个源文件 到目标目录; 或采用另一种方式, 利用 -t Directory SOURCE... 参数-t将目标目录放在前面来
而且, mv命令可以直接操作 源目录, 不必加-r选项! mv sourceDir destDir
mv SOURCE DEST : 更名
mv [OPTION]... SOURCE... DIRECTORY
or: mv [OPTION]... -t DIRECTORY SOURCE...
Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY.
===================================================
一个例子, 一个管理主机启动过程的程序, 入口主类是 Hostlauncher.java, 要管理CMOS, 内存memory,硬盘disk的启动launch过程.那么这些组件的启动过程不可能全部写到启动主类中, 而且所有的计算机主机的启动过程都差不多,可以通用的,所以将这些组件的启动写成 类, 然后组织到文件夹中, 因为要提供给外部其他程序使用,所以,需要将它们打包成jar文件(jar跟package类似,只不过archive了一下,也是等同于一个 classpath, -cp路径而已'
不管是使用包package, 还是使用 jar文件, 在你的主类中, 都要能正确地找到你所要引用的类(不管是使用相对目录还是绝对路径), 就要求: 你的主类java文件要能 "看到"/正确找到包/jar的 开始路径, 即引用的 package path1.path2.className 语句中的 path1 要能对主类可见
对于jar文件: 满足两个条件: 1是jar文件要对 主类java文件可见, 即要找得到这个jar文件; 2是jar文件中的目录和主类java文件中 package引用的目录要一致, 这样草才能让主类java找到所引用的类!
由于普通用户 只能访问它自己的家目录, 不能访问像/opt之类的 root目录. 所以 这些java, jar之类的文件还是放到自己的家目录中吧,免得引起访问权限的麻烦
javac编译是静态的, java才是 动态执行的, 所以 Exception异常是在 程序执行过程中才发生的 , 是在 动态查找,绑定方法等时候, 才发生的.
java执行时, 同样要指定 -cp jar-path的, 否则会报: java.lang.NoClassDefFoundError 这个异常.
文件目录树: Hostlauncher.java和hostUtil在同一目录下
[lee@localhost ~]$ tree hostUtil/
hostUtil/
├── boardUtil
│ ├── utilCMOS.class
│ ├── utilCMOS.java
│ ├── utilCMOS.java!
│ ├── utilDisk.java
│ └── utilMemory.java
└── peripheralUtil
2 directories, 5 files
import hostUtil.boardUtil.utilCMOS;
/**
* 主机启动程序的入口主类
* 由它加载其他自举类, 包括读取CMOS,加载内存, 读取硬盘等操作
* @author Lee
*/
public class Hostlauncher{
/**
* main class executing entry point
*/
public static void main(String[] args){
System.out.println("Host lanucher Program is running now, it will load CMOS, Memory and Disk etc. modules.
");
System.out.println("=== loading CMOS module ===");
utilCMOS.utCMOSRead();
utilCMOS.utCMOSRewrite(" myCMOSProfiles");
System.out.println("
=== loading Memory module ===
......
Memory loading method...
Memory is loaded successfully");
System.out.println("
=== loading Disk module ===
......
Disk loading method...
Disk is loaded successfully");
}
}
package hostUtil.boardUtil;
public class utilCMOS{
public static void main(String[] args){
System.out.println("utilCMOS: using utilCMOS class could help you to operate CMOS data");
}
public static String utCMOSRead(){
System.out.println("utilCMOS reading begin ...");
System.out.println("utilCMOS reading method ...");
System.out.println("utilCMOS reading end");
return "utCMOS data is read successfully!";
}
public static boolean utCMOSRewrite(String cmosDataToRewritten){
System.out.println("utilCMOS rewriting begin ...");
System.out.println("utilCMOS rewriting method: To write "" + cmosDataToRewritten +"" into CMOS, ...");
System.out.println("utilCMOS rewriting end and data is rewritten successfully!");
return true;
}
}
执行结果:
[lee@localhost ~]$ java Hostlauncher
Host lanucher Program is running now, it will load CMOS, Memory and Disk etc. modules.
=== loading CMOS module ===
utilCMOS reading begin ...
utilCMOS reading method ...
utilCMOS reading end
utilCMOS rewriting begin ...
utilCMOS rewriting method: To write " myCMOSProfiles" into CMOS, ...
utilCMOS rewriting end and data is rewritten successfully!
=== loading Memory module ===
......
Memory loading method...
Memory is loaded successfully
=== loading Disk module ===
......
Disk loading method...
Disk is loaded successfully
当使用jar文件时:
[lee@localhost ~]$ jar cvf hostUtil.jar hostUtil/
added manifest
adding: hostUtil/(in = 0) (out= 0)(stored 0%) // 创建目录时的in, out 都为0
adding: hostUtil/peripheralUtil/(in = 0) (out= 0)(stored 0%)
adding: hostUtil/boardUtil/(in = 0) (out= 0)(stored 0%)
adding: hostUtil/boardUtil/utilCMOS.java(in = 789) (out= 299)(deflated 62%)
adding: hostUtil/boardUtil/utilCMOS.class(in = 1166) (out= 630)(deflated 45%)
adding: hostUtil/boardUtil/utilMemory.java(in = 0) (out= 0)(stored 0%)
adding: hostUtil/boardUtil/utilCMOS.java!(in = 728) (out= 271)(deflated 62%)
adding: hostUtil/boardUtil/utilDisk.java(in = 0) (out= 0)(stored 0%)
编译:
[lee@localhost ~]$ javac -cp hostUtil.jar Hostlauncher.java
如果不指定java 时的 -cp会发生异常:
[lee@localhost ~]$ java Hostlauncher
Host lanucher Program is running now, it will load CMOS, Memory and Disk etc. modules.
=== loading CMOS module ===
Exception in thread "main" java.lang.NoClassDefFoundError: hostUtil/boardUtil/utilCMOS
at Hostlauncher.main(Hostlauncher.java:13)
#### 特别注意的是, 如果 jar文件和 当前java文件不在同一个目录的时候, 指定 -cp 类路径的时候, 一定要加上 .点号, 即表示当前目录, 因为java在执行的时候, 只会从你指定的类路径下去查找类, 查找所有的类, 包括你要执行的主类, 如果你的类路径中,不包含当前路径的话, 就只是到jar中去找, 当然就找不到 主类的入口了.
即: ` java -cp ~/reflib/someReferenced.jar:. Hostlauncher `
==================================================
java类的所有成员方法都是virtual虚的, 另一方面, 它又支持方法的重载,所以它就不支持 方法的参数默认值
它是c++的删减版, 对c++的一些特性做了删减. 在c++的类的虚方法中也不要用默认参数值
java通过函数的重载来实现默认值(两个同名函数, 在使用参数默认值(参数少的)方法中,调用那个参数多的方法, 使用this或同名函数名.比如: public String showDate(int year,int month, int date){ showDate(...) / this("2000", "03", "10", "12","10"); } public String showDate(int year, int month, int date, int hour, int minute){..println(year+"-"+month+"-"+date+" " +hour+":"+minute);}