zoukankan      html  css  js  c++  java
  • 如何创建和使用 jar文件中 的类?

    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);}

    实际上,不管在linux还是win中, 同一个程序中的 多个标签页之间切换,用的都是ctrl+PgUp, ctrl+PgDn

    当添加自定义的 manifest文件时, 还是会在jar包中 , 创建 META-INF/MANIFEST.MF文件, 而且不会包含你的 自定义manifest 文件, 只是把你的manifest文件 "append to" 追加到 原来的 MANIFEST.MF文件中. 比如你在manifest文件中定义自己的主类: Main-Class: somepackage1.pack2.mainClass

  • 相关阅读:
    NHibernate 入门必看——NHibernate Made Simple
    ASP.NET 的多线程
    asp.net 禁止用户二次登录(转)
    marquee标记用法及在asp.net中的应用(转)
    解决Visual Studio 2005显示中文乱码(zhuan)
    ms sql 触发器( 转)
    Asp.net 页面导航的几种方法与比较
    ASP.NET1.1(VB):DataGrid中"加入序号列"和"截取定长字符串追加'...
    解决“Internet Explorer 无法打开 Internet站点已终止操作”问题(转)
    ASP.NET 2.0的页面指令集(转)
  • 原文地址:https://www.cnblogs.com/bkylee/p/13687445.html
Copyright © 2011-2022 走看看