Java中jar包的创建和使用

news2024/11/17 16:16:22

Java中jar包的创建和使用

jar包的基本概念

jar包的全称是java archivejar包本质就是一种压缩包。在Java开发中一般是用来压缩类的一个包。类似C/C++中的静态库和动态库,但是又不完全是。

C/C++中的静态库和动态库是对中间文件(*.o)打包成一个二进制包。

  • 如果是静态库,则在编译可执行文件(*.exe)的时候把静态库和可执行文件编译到一起。
  • 如果是动态库,则单独编译完可执行文件后,执行可执行文件时动态加载动态库。

Java的jar包是对编译好的字节码打包到一个jar包中。jar包分为以下两类:

  • 不带主类
  • 带主类

不带主类的jar包就和C/C++的库差不多了,带主类的jar包在运行的时候就需要使用jar.exe来运行。

命令行生成jar包

不带主类

先把源文件写好,尽量使用简单点的例子,要不然容易把重心放到源文件的代码编写上了,我们这里的重点是讲jar包,不是源文件的具体功能。

我们以封装一个计算器类为例,然后把这个类打包供其他类使用。

在随便一个项目目录下创建cukor/calc文件夹。然后创建MyCalc.java文件,内容如下:

package cukor.calc;

public class MyCalc {
    // 加法
    public static int add(int... numbers) {
        int sum = 0;
        for (int i : numbers) {
            sum += i;
        }
        return sum;
    }
    // 减法
    public static int sub(int... numbers) {
        int first = numbers[0];
        for (int i = 1; i < numbers.length; i++) {
            first -= numbers[i];
        }
        return first;
    }
    // 乘法
    public static int mult(int... numbers) {
        int result = 1;
        for (int i : numbers) {
            result *= i;
        }
        return result;
    }
    // 除法
    public static int div(int... numbers) {
        int first = numbers[0];
        for (int i = 1; i < numbers.length; i++) {
            try {
                first /= numbers[i];
            } catch(Exception e) {
                System.out.println("除数不能为0,程序异常:" + e.getMessage());
            }
        }
        return first;
    }
}

上面的MyCalc应该是没问题的,就分别封装了加、减、乘、除功能的四个静态成员函数,类外不用创建对象调用,直接使用类名来调用。

然后编写一个主类来调用它,回到项目目录,创建Main.java文件,内容如下:

import cukor.calc.MyCalc;		// 导入刚刚写好的类
public class Main {
    public static void main(String[] args) {
        int result;
        result = MyCalc.add(1, 0, 3, 4);
        printResult("加法", result);
        result = MyCalc.sub(9, 32, 3, -10);
        printResult("减法", result);
        result = MyCalc.mult(4, 3, 2);
        printResult("乘法", result);
        result = MyCalc.div(4, 2, -1);
        printResult("除法", result);
        System.out.println("程序结束");
    }
    public static void printResult(String string, int result) {
        System.out.println(string + result);
    }
}

编译MyCalc.java

javac cukor/calc/MyCalc.java

编写Manifest文件:

自定义命名,但是要以.mf为拓展名,如MyCalc.mf

Manifest-Version: 1.0
Class: cukor/calc/MyCalc
Create-By: 19
  • Manifest-Version: 1.0:指定jar包的版本是1.0
  • Class: cukor/calc/MyCalc:指定jar包中包含的类
  • Create-By: 19:指定JDK版本

创建MyCalc.jar

jar -cfm MyCalc.jar MyCalc.mf cukor/calc/*.class

其中-cfm:是-c-f-m的结合简写,它们的解释可以在终端输入下面的命令查看:

jar --help

截取这几个选项的说明:

  -c, --create               创建档案。通过 -f 或 --file 指定的档案文件名
                             包含路径时,还将创建
                             缺少的父目录
  -f, --file=FILE            档案文件名。省略时, 基于操作
                             使用 stdin 或 stdout
      --release VERSION      将下面的所有文件都放在
                             jar 的版本化目录中 (即 META-INF/versions/VERSION/)
  -m, --manifest=FILE        包含指定清单文件中的
                             清单信息
  • MyCalc.jar:生成的jar包的名字
  • MyCalc.mf:jar包清单文件,刚刚写好的
  • cukor/calc/*.class:实际打包的类,其中*表示通配符,也可以指定全部名字

如果程序没有报错的话,查看当前项目目录应该得到下面的结果,如果报错了就检查一下那里不一样,并更改。

PS D:\myCoding\Terminal\Java\TestJar> ls

    Directory: D:\myCoding\Terminal\Java\TestJar

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----    2023/4/16 星期日    12:31                cukor
-a---    2023/4/16 星期日    12:38            526 Main.java
-a---    2023/4/16 星期日    12:48           1334 MyCalc.jar
-a---    2023/4/16 星期日    12:43             64 MyCalc.mf

如果使用压缩软件打开MyCalc.jar会看到下面的结果,这里以Bandzip为例。

请添加图片描述

请添加图片描述

请添加图片描述

这个时候可以把cukor文件夹删掉。因为我们已经打包了,为了防止Main.java编译的时候会依赖cukor文件夹,所以我们需要把它删除或者移动到其他位置。

然后编译Main.java

javac -cp ".;MyCalc.jar" Main.java

然后运行Main.class

java -cp ".;MyCalc.jar" Main
  • -cp ".;MyCalc.jar":表示临时使用classpath环境变量为:".;MyCalc.jar",jar包是一定要带上的要不然会报找不到类的错误。而且是编译和运行都要带上。如果依赖多个jar包就顺着写然后使用逗号分隔就可以了。例如".;MyCalc.jar;Test.jar;Test2.jar;".

输出结果:

加法8
减法-16
乘法24
除法-2
程序结束

如果Main.java中使用了package,那么在运行的时候一定要带上包名。

带主类

新建一个项目(新的文件夹下)。防止和上面的混乱。

上面的jar包是不带主类的,下面就把主类也打包到jar包中,然后使用jar命令来运行,而不是用java

代码还是上面的,只是我们现在的MyCalc2.jar要包含原来的MyCalc.class和主类Main.class

可以把上一个项目的文件直接拷贝过来。然后用解压软件把MyCalc.jar解压,然后只保留需要的cukor/calc/MyCalc.class。路径也是保留的,要不然Main.java编译不了。

编译Main.java

javac Main.java

如果报错了,说找不到类,那肯定是没有保留住cukor文件夹及其子目录,因为Main.java中导入包的代码是import cukor.calc.MyCalc;,那包路径没有保留当然是报错的。

然后写Manifest文件(.mf为后缀):

Manifest-Version: 1.0
Main-Class: Main
Create-By: 19

创建MyCalc2.jar

jar -cfm MyCalc2.jar manifest.mf Main.class cukor/calc/*.class

然后运行MyCalc2.jar

java -jar MyCalc2.jar

输出结果:

加法8
减法-16
乘法24
除法-2
程序结束

VSCode生成jar包

VSCode适合小型一点的java项目,大一点的项目需要不太合适,使用VSCode来封装jar包的过程中也可以学习到关于jdk命令行的一些小知识,虽然好像也没什么用,但是了解一下还是可以的。

首先需要在VSCode里安装Java拓展包插件:

请添加图片描述

然后创建Java项目:

请添加图片描述

项目类型:(一般项目即可)
请添加图片描述

然后跳出一个选择文件夹的框,选择一个文件路径就可以,这个是你的当前项目的路径。

项目结构:

请添加图片描述

  • .vscode:放置项目属性设置,包括生成路径、classpath的路径、jar包的路径。
  • bin:字节码的输出路径
  • libjar包的存放路径
  • src:项目源文件路径
  • App.java:默认生成的主类源文件
  • Readme.md:项目说明文档

可以打开Readme.md查看当前项目结构的具体信息。

那现在开始写代码:其实还是用上面的代码。

  • App.java
import cukor.calc.MyCalc;		// 导入刚刚写好的类
public class App {
    public static void main(String[] args) {
        int result;
        result = MyCalc.add(1, 0, 3, 4);
        printResult("加法", result);
        result = MyCalc.sub(9, 32, 3, -10);
        printResult("减法", result);
        result = MyCalc.mult(4, 3, 2);
        printResult("乘法", result);
        result = MyCalc.div(4, 2, -1);
        printResult("除法", result);
        System.out.println("程序结束");
    }
    public static void printResult(String string, int result) {
        System.out.println(string + result);
    }
}
  • MyCalc.java
package cukor.calc;

public class MyCalc {
    // 加法
    public static int add(int... numbers) {
        int sum = 0;
        for (int i : numbers) {
            sum += i;
        }
        return sum;
    }
    // 减法
    public static int sub(int... numbers) {
        int first = numbers[0];
        for (int i = 1; i < numbers.length; i++) {
            first -= numbers[i];
        }
        return first;
    }
    // 乘法
    public static int mult(int... numbers) {
        int result = 1;
        for (int i : numbers) {
            result *= i;
        }
        return result;
    }
    // 除法
    public static int div(int... numbers) {
        int first = numbers[0];
        for (int i = 1; i < numbers.length; i++) {
            try {
                first /= numbers[i];
            } catch(Exception e) {
                System.out.println("除数不能为0,程序异常:" + e.getMessage());
            }
        }
        return first;
    }
}

VSCode不需要我手动编译,当我保存文件的时候自动帮我编译了。

请添加图片描述

那就直接生成jar包吧。

通过控制面板找项目视图

请添加图片描述

左下角有项目视图

请添加图片描述

然后生成jar包。

请添加图片描述

带主类的就选App,不带主类就选<without main class>

现在选择第二个,第一个自己试了,都是一样的操作,只是等下生成的Manifest文件的内容不一样而已,不一样的就一行。但打包到jar包中的结果是一样的,就是选<without main class>也会把App.class包含进去。

打包成功VSCode右下角就出现下面的弹框。

请添加图片描述

在当前项目目录下就生成了TestCode.jar,这个名字和项目名称相同。

请添加图片描述

然后可以删除或者移动cukor/calc/MyCalc.java,把bin目录下的文件都删除了。把TestCode.jar移动到lib文件夹下。

程序没有报错,并且重新自动编译好了新的App.class

请添加图片描述

直接运行,没有任何问题。

请添加图片描述

注意,这里不要自己手动运行,因为VSCode在自动帮我们编译的时候使用了--enable-view选项,所以在运行的时候如果是我们自己手动运行,那么很容易漏掉这个选项,导致报错,而VSCode自带的运行就会自己加上这个选项所以不会报错。

其中'@C:\Users\ADMINI~1\AppData\Local\Temp\cp_ab0491xg1nsgvk4j00lx26h1u.argfile'是一个超链接,会连接到本地的文件夹打开对应的文件,读取文件中的内容,并把内容替换这个超链接。

注意,这个超链接链接到的文件是在Temp文件夹下的,所以其实可以随便删除,这个只是一个临时文件。

ctrl+鼠标左键单击那个超链接,打开可以看到是下面的内容:

 --enable-preview -XX:+ShowCodeDetailsInExceptionMessages -cp "D:\\myCoding\\Terminal\\Java\\Test\\TestCode\\bin;d:\\myCoding\\Terminal\\Java\\Test\\TestCode\\lib\\TestCode.jar"

除了路径和我的不一样之外,其他的应该是一样的。可以看到,VSCode在运行的时候传递给java.exe的参数中就有刚刚提到的--enable-preview。是因为我使用的JDK是19的版本,并不是一个长期支持的版本,所以就会有这个选项,其实如果在编译的时候不加这个--enable-preview选项,也是可以的,但是在运行的时候就不能加。即对于--enable-preview选项要么编译运行都加要么就都不要加。-XX:+ShowCodeDetailsInExceptionMessages表示的是如果程序有什么异常的就会把对应的异常信息打印到控制台上。-cp就是用来临时改变classpath环境变量的,因为我们用到了我们自己的jar包,所以一定要把我们的jar包路径配置到classpath环境变量中。

IDEA生成jar包

创建好项目后创建源文件。

  • Main.java
package TestCode;

import TestCode.cukor.calc.MyCalc;

public class Main {
    public static void main(String[] args) {
        int result;
        result = MyCalc.add(1, 0, 3, 4);
        printResult("加法", result);
        result = MyCalc.sub(9, 32, 3, -10);
        printResult("减法", result);
        result = MyCalc.mult(4, 3, 2);
        printResult("乘法", result);
        result = MyCalc.div(4, 2, -1);
        printResult("除法", result);
        System.out.println("程序结束");
    }

    public static void printResult(String string, int result) {
        System.out.println(string + result);
    }
}
  • MyCalc.java
package TestCode.cukor.calc;

public class MyCalc {
    // 加法
    public static int add(int... numbers) {
        int sum = 0;
        for (int i : numbers) {
            sum += i;
        }
        return sum;
    }

    // 减法
    public static int sub(int... numbers) {
        int first = numbers[0];
        for (int i = 1; i < numbers.length; i++) {
            first -= numbers[i];
        }
        return first;
    }

    // 乘法
    public static int mult(int... numbers) {
        int result = 1;
        for (int i : numbers) {
            result *= i;
        }
        return result;
    }

    // 除法
    public static int div(int... numbers) {
        int first = numbers[0];
        for (int i = 1; i < numbers.length; i++) {
            try {
                first /= numbers[i];
            } catch (Exception e) {
                System.out.println("除数不能为0,程序异常:" + e.getMessage());
            }
        }
        return first;
    }
}

我当前的项目目录:

请添加图片描述

然后开始创建jar包。

文件->项目结构->

请添加图片描述

工件->加号->JAR->来自具有依赖项的模块中。

找主类:

请添加图片描述

请添加图片描述

前面只是一堆设置,下面才是构建生成jar包,IDEA比较麻烦。

请添加图片描述

请添加图片描述

然后在out路径下就生成了Demo.jar包。

请添加图片描述

但是,使用解压工具打开会发现,它把所有的软件包都打包进去了。。。。

请添加图片描述

第二次选择空项目。

请添加图片描述

请添加图片描述

请添加图片描述

然后同样的方式构建jar包。但是下面要选择test.jar.

请添加图片描述

然后生成了test.jar.

请添加图片描述

使用解压软件打开看一下。

没有任何区别。然而更麻烦了。

在这里插入图片描述

好了,关于jar包的创建和使用就说这么多,eclipse的就自己玩吧。同样的道理,其实理解了命令行版本的,图形化版本的都好理解。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/419651.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【电路原理】电路元件基本知识详解

博主简介&#xff1a;努力学习的22级计科生一枚~博主主页&#xff1a; 是瑶瑶子啦所属专栏: 电路理论 前言1.电阻元件2.电容元件3.电感元件4.独立电源4.1&#xff1a;电压源4.2&#xff1a;电流源5.受控电源6.符号补充&#xff1a;7.总结本专栏文章主要总结、归纳电路原理、电路…

数据结构-排序(2)

前言&#xff1a; 上一章节介绍了 排序中的插入排序和选择排序&#xff0c; 分别复盘了插入排序中的直接插入排序和希尔排序以及选择排序中的选择排序和堆排序。今天继续复盘交换排序。 目录 2.3交换排序 2.3.1冒泡排序 2.3.2快速排序 2.3.2快速排序非递归 2.3交换排序 基…

HTML5 <figure> 标签、HTML5 <footer> 标签

HTML5 <figure> 标签 实例 使用 <figure> 元素标记文档中的一个图像&#xff1a; <figure><img src"img_pulpit.jpg" alt"The Pulpit Rock" width"304" height"228"> </figure>尝试一下 浏览器支持 …

在proteus中仿真arduino实现矩阵键盘程序

矩阵键盘是可以解决我们端口缺乏的问题&#xff0c;当然&#xff0c;如果我们使用芯片来实现矩阵键盘的输入端口缺乏的问题将更加划算了&#xff0c;本文暂时不使用芯片来解决问题&#xff0c;而使用纯朴的8根线来实现矩阵键盘&#xff0c;目的是使初学者掌握原理。想了解使用芯…

Lua脚本

目录说明什么是Lua脚本为什么要使用Lua脚本Lua脚本的安装Lua脚本的使用Lua的变量Lua脚本的算术运算符Lua脚本的关系运算符Lua脚本的逻辑运算符Lua脚本不同的操作Lua脚本的函数和标准库Redis整合Lua脚本&#xff08;重点&#xff09;在Java集成Lua在SpringBoot项目中使用Redis集…

前端PC端适配,网页端适配

问题背景 由于我司是使用的大屏&#xff0c;且设计稿尺寸为19201080。但是需要适配各种分辨率&#xff0c; 比如12801024(5:4)、1366768(16&#xff1a;10)、16801050&#xff08;16&#xff1a;10&#xff09;。在尝试了多种方法之后&#xff0c;最终确定主要的适配方法为rem…

【vue3】04-vue基础语法补充及阶段案例

文章目录vue基础语法补充vue的computedvue的watch侦听书籍购物车案例vue基础语法补充 vue的computed computed&#xff1a;用于声明要在组件实例上暴露的计算属性。&#xff08;官方文档描述&#xff09; 我们已经知道&#xff0c;在模板中可以直接通过插值语法显示一些data中…

科学的演变:从笛卡尔到生成式人工智能

编者按&#xff1a;本文主要介绍了科学的演变历史&#xff0c;从笛卡尔到生成式人工智能。文章探讨了数学在验证科学原理中的作用&#xff0c;并介绍了新机器学习工具如何验证新的科学。 文中提到&#xff0c;将生成式人工智能与Excel或iPhone进行比较是低估了这一新技术的潜在…

【AI】PaddlePaddle实现自动语音识别

文章目录文档背景安装环境Python版本pip环境安装模型需要的环境项目目录结构数据准备生成数据字典数据预处理训练模型创建模型构建模型的目的模型黑盒在模型中充当什么角色解码方法总结文档背景 学习AI的过程中&#xff0c;难免会出现各种各样的问题。比如&#xff0c;什么样的…

制造业生产管理系统(500强制造企业数字化实践)

前言 制造业是国民经济的支柱产业之一&#xff0c;随着科技和数字化的发展&#xff0c;制造业正在经历着一场新的变革。传统的制造模式已经无法满足市场的快速变化和客户的多样化需求&#xff0c;制造企业急需通过数字化和智能化转型升级&#xff0c;提高生产效率和质量水平&a…

第十四届蓝桥杯嵌入式详解

目录 第一部分 客观试题&#xff08;15 分&#xff09; 不定项选择&#xff08;1.5 分/题&#xff09; 第二部分 程序设计试题&#xff08;85 分&#xff09; 2.1 STM32CubeMX初始化配置 2.1.1 配置GPIO 2.1.2 配置ADC 2.1.3 配置RCC 2.1.4 配置定时器TIM 2.1.5 配置ADC1、AD…

【从零开始学Skynet】基础篇(二):了解Skynet

1、节点和服务 在下图所示的服务端系统中&#xff0c;每个Skynet进程&#xff08;操作系统进程&#xff09;都称为一个节点&#xff0c;每个节点都可以开启数千个Lua服务&#xff0c;每个服务都是一个Actor。不同节点可以部署在不同的物理机上&#xff0c;提供分布式集群的能力…

Velocity入门到精通(上篇)

最近自己所做的项目使用到这个Velocity模板引擎&#xff0c;分享一下在互联网找的学习资料。 目录 一. velocity简介 1. velocity简介 2. 应用场景 3. velocity 组成结构 二. 快速入门 1. 需求分析 2. 步骤分析 3. 代码实现 3.1 创建maven工程 3.2 引入坐标 3.3 编…

Redis锁的租约问题

目录Redis的租约问题Redis租约问题的想法Redis租约问题的解决方案Redis的租约问题 首先我们先来说一说什么是Redis的租约问题。   在我们实现Redis分布式锁的时候&#xff0c;我们会出现Redis锁的时间<业务执行执行时间&#xff0c;这其实就是一个典型的租约问题&#xf…

【C++】你了解命名空间吗?

C语言之父&#xff1a;Bjarne Stroustrup博士(本贾尼) 当我们在编写代码的时候&#xff0c;可能会产生一些命名冲突&#xff0c;为了解决这一冲突我们引出命名空间的概念 (ps:命名冲突的产生主要包括两个方面原因&#xff1a;1、与库函数名冲突&#xff1b;2、相互之间的冲突&…

【LeetCode】剑指 Offer 51. 数组中的逆序对 p249 -- Java Version

题目链接&#xff1a;https://leetcode.cn/problems/shu-zu-zhong-de-ni-xu-dui-lcof/ 1. 题目介绍&#xff08;51. 数组中的逆序对&#xff09; 在数组中的两个数字&#xff0c;如果前面一个数字大于后面的数字&#xff0c;则这两个数字组成一个逆序对。输入一个数组&#xf…

python3 DataFrame一些好玩且高效的操作

pandas在处理Excel/DBs中读取出来&#xff0c;处理为DataFrame格式的数据时&#xff0c;处理方式和性能上有很大差异&#xff0c;下面是一些高效&#xff0c;方便处理数据的方法。 map/apply/applymaptransformagg遍历求和/求平均shift/diff透视表切片&#xff0c;索引&#x…

VS Code 将推出更多 AI 功能给 Java 开发者

大家好&#xff0c;欢迎来到我们的二月更新&#xff01;我们将为您带来与 JUnit 5 并行测试相关的新功能以及用于 Spring Boot Dashboard 的过滤功能。另外&#xff0c;OpenAI 和 ChatGPT 是最近的热点&#xff0c;所以在 GitHub Copilot 方面也有一些令人激动的消息&#xff0…

【郭东白架构课 模块二:创造价值】19|节点二:架构活动的目标为什么常常被忽略?

你好&#xff0c;我是郭东白。从这节课开始&#xff0c;我们就进入到架构活动第二个环节的学习&#xff0c;那就是目标确认。 为架构活动确认一个正确目标&#xff0c;是架构师能为架构活动做出最大贡献的环节。从我的个人经验来看&#xff0c;一大半架构活动的目标都不具备正…

类文件具有错误的版本 55.0, 应为 52.0

最近在编译时报如下错误 java: 无法访问com.xx错误的类文件: /xxx.jar!/aa.class类文件具有错误的版本 55.0, 应为 52.0请删除该文件或确保该文件位于正确的类路径子目录中。 原来我依赖的jar包的编译版本是jdk11,而我本地代码编译的版本的jdk1.8,两个版本不一致&#xff0c;所…