一、生活化理解(先有个画面)
想象你要做一道“番茄牛腩面”:
原材料:番茄、牛腩、面条、香料(分散的)
打包好的方便面:面饼+调料包+脱水蔬菜,全在一个袋子里(JAR 包)
你只要拆开袋子,开水一泡就能吃(引入 JAR 包就能直接用)
JAR 包就是 Java 世界的“方便面”——它把一堆编译好的.class文件、配置文件、资源文件打包成一个文件,别人拿来就能用,不用自己从头炒料。
二、JAR 包的标准定义
JAR(Java Archive)是一种压缩文件格式,基于 ZIP 格式,用于聚合多个 Java 类文件、元数据和资源文件(图片、配置文件等)。
作用:
分发:把写好的功能打包发给别人。
复用:别人引入你的 JAR,就能调用里面的类和方法。
模块化:按功能拆分(如
commons-lang.jar处理字符串,mysql-connector.jar连接数据库)。
三、JAR 包内部结构(打开看看)
用解压软件打开一个 JAR 包,通常看到:
text
my-app.jar ├── META-INF/ │ └── MANIFEST.MF # 清单文件(记录版本、主类等) ├── com/ │ └── example/ │ ├── Main.class # 编译后的字节码 │ └── Utils.class ├── config/ │ └── application.properties └── static/ └── logo.png
MANIFEST.MF很重要:可执行 JAR 会在这里指定Main-Class(入口类)。
四、怎么生成 JAR 包(带代码操作)
场景1:用jar命令手动打包
写两个简单类:
Calculator.java
java
package com.demo; public class Calculator { public int add(int a, int b) { return a + b; } }MainApp.java
java
package com.demo; public class MainApp { public static void main(String[] args) { Calculator calc = new Calculator(); int result = calc.add(10, 20); System.out.println("Result: " + result); } }编译:
bash
javac -d . Calculator.java MainApp.java
(会在当前目录生成com/demo/*.class)
打包成 JAR:
bash
jar cvf my-app.jar com/
c创建v显示详细f指定文件名
执行 JAR(需要指定主类):
bash
java -cp my-app.jar com.demo.MainApp
场景2:制作“可执行 JAR”(双击运行)
写一个MANIFEST.MF文件:
text
Manifest-Version: 1.0 Main-Class: com.demo.MainApp
注意:最后必须有一个空行。
打包时把清单加进去:
bash
jar cvfm my-exec.jar MANIFEST.MF com/
运行:
bash
java -jar my-exec.jar
五、开发中最常见的用法:Maven/Gradle 管理依赖
现实项目中,几乎不用手动打包,而是用构建工具。
Maven 的pom.xml依赖片段:
xml
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.12.0</version> </dependency>
当你执行mvn compile,Maven 会自动从中央仓库下载commons-lang3-3.12.0.jar到本地~/.m2/repository/,并加入 classpath。
Gradle 的build.gradle:
gradle
dependencies { implementation 'org.apache.commons:commons-lang3:3.12.0' }六、代码里如何使用 JAR 包里的类
假设你引入了commons-lang3.jar,代码中直接 import:
java
import org.apache.commons.lang3.StringUtils; public class Demo { public static void main(String[] args) { // 判断字符串是否为空(来自 JAR 包) boolean empty = StringUtils.isEmpty(" "); System.out.println(empty); // false(因为空格不算空,如果用isBlank则true) // 反转字符串 String reversed = StringUtils.reverse("hello"); System.out.println(reversed); // olleh } }编译运行时的 classpath 必须包含该 JAR:
bash
javac -cp commons-lang3-3.12.0.jar Demo.java java -cp .:commons-lang3-3.12.0.jar Demo # Windows用分号;
七、JAR 包的“三大派系”
| 类型 | 说明 | 典型例子 |
|---|---|---|
| 普通 JAR | 只包含自己编译的类 | 你的业务代码 |
| 可执行 JAR | MANIFEST.MF 指定了Main-Class,可用java -jar运行 | Spring Boot 打出的 fat jar |
| Fat JAR / Uber JAR | 把自己+所有依赖的三方 JAR 都解压再重新打包成一个超大 JAR | Spring Boot 微服务部署包 |
Spring Boot 的 Fat JAR 内部甚至还有BOOT-INF/lib目录存放依赖 JAR。
八、一个完整“打包-引用”实战(模拟真实协作)
步骤1:A 同学写工具类,打成 JAR 发给 B。
工具类DateUtil.java:
java
package com.util; import java.time.LocalDate; public class DateUtil { public static String today() { return LocalDate.now().toString(); } }打包:
bash
javac -d . DateUtil.java jar cvf date-util.jar com/
步骤2:B 同学拿到date-util.jar,复制到项目的lib/文件夹,然后引用:
B 的主程序App.java:
java
import com.util.DateUtil; public class App { public static void main(String[] args) { System.out.println("Today is " + DateUtil.today()); } }编译运行:
bash
javac -cp lib/date-util.jar App.java java -cp .:lib/date-util.jar App
九、常见面试/概念题
JAR 和 WAR 的区别
JAR:普通 Java 应用或库
WAR:Web 应用归档,包含 WEB-INF/web.xml、JSP、Servlet 等,部署到 Tomcat/Jetty
JAR 包冲突怎么解决
Maven 的
dependency:tree查看依赖树用
<exclusion>排除传递依赖或者升级/降级版本统一
怎么查看 JAR 包里的类
bash
jar tf my-app.jar # 列出所有文件 javap -cp my-app.jar com.demo.Calculator # 反编译查看方法签名
十、总结一句话
JAR 包 = Java 的压缩归档文件,是代码复用的基本单元,通过 classpath 引入,可以被构建工具自动管理,也可以手动打包分发。