news 2026/4/21 2:47:55

Java程序的生命周期--建立时间概念

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java程序的生命周期--建立时间概念

时间概念没建立

❌ 写代码时
❌ 编译时
❌ 运行时

这三个在脑子里是“糊在一起的”。

今天这条,我只干一件事:
把这三个时间点,用“人能理解的方式”彻底分开。
不讲 Spring,不讲 MapStruct,不讲 IOC。
先把“时间轴”立起来。

一、先给你一句“总纲版结论”(先记住)

Java 程序一生分 4 个阶段:

1️⃣ 写代码时(你在敲代码)
2️⃣ 编译时(javac 在干活)
3️⃣ 启动时(JVM + 框架启动)
4️⃣ 运行时(程序正在跑)

你现在最大的问题是:把 1、2、3、4 当成一坨了

二、第一阶段:什么叫「写代码时」?

1️⃣ 写代码时 = 你坐在电脑前敲字

public class User { private String name; }

这个阶段的特点:

  • ❌ 程序还没运行
  • ❌ JVM 还没启动
  • ❌ Spring 完全不存在
  • ❌ MapStruct 不存在
  • ❌ 反射不存在

📌这只是“文本文件”

就像你在 Word 里打字一样。

2️⃣ 写代码时你能做什么?

你只能:

  • 写类
  • 写方法
  • 写注解
  • 写 if / for

不能

  • new 一个对象(还没运行)
  • 调一个方法
  • 注入一个 Bean

3️⃣ 非常关键的一句话

写代码时,你是在“描述未来会发生什么”
但事情还没发生

三、第二阶段:什么叫「编译时」?

4️⃣ 编译时 = javac 开始工作

你点了:

Run / Build / mvn package

这时发生:

.java → javac → .class

5️⃣ 编译时 JVM 启动了吗?

没有

这点非常非常重要。

编译时:

  • ❌ 没有 main 方法执行
  • ❌ 没有 Spring Boot 启动
  • ❌ 没有数据库连接
  • ❌ 没有对象实例

6️⃣ 编译时 javac 在干什么?

主要干 3 件事:

① 语法检查

int a = "hello"; ❌

直接报错

② 类型检查

User u = new Order(); ❌

编译不过

注解处理器(超级重要)

MapStruct、Lombok 就在这一步出现

7️⃣ MapStruct 发生在这里(关键)

@Mapper public interface WorkOrderConverter { }

编译时:

  • javac 发现 @Mapper
  • MapStruct 的注解处理器被触发
  • 生成:
WorkOrderConverterImpl.java

📌注意:此时程序还没运行

8️⃣ 一句话总结编译时

编译时 = 把你写的代码“加工成能运行的代码”

四、第三阶段:什么叫「启动时」?

9️⃣ 启动时 = JVM 启动 + 框架初始化

你点了:

Run Application

发生:

JVM 启动 ↓ 加载 .class ↓ 执行 main 方法

🔟 Spring Boot 的启动就在这里

public static void main(String[] args) { SpringApplication.run(App.class, args); }

📌Spring IOC 容器是在“启动时”创建的

1️⃣ 1️⃣启动时 Spring 在干什么?

(这个需要以后慢慢啃的)

  • 扫描 classpath
  • 找 @Component / @Service / @Mapper
  • new 对象
  • 放进 IOC 容器
  • 建立依赖关系

⚠️ 这一步不是编译时

五、第四阶段:什么叫「运行时」?

1️⃣2️⃣ 运行时 = 程序已经启动,正在服务用户

例如:

  • 你访问接口
  • Controller 方法被调用
  • Service 逻辑执行
  • DAO 操作数据库

1️⃣3️⃣ 反射发生在这里(重点)

clazz.getDeclaredConstructor().newInstance();

👉反射一定发生在运行时

原因很简单:

编译时你不知道是哪个类
只有运行时才能知道


六、把四个阶段放在一条“时间轴”上

你敲代码 ↓ 写代码时 ↓ javac ↓ 编译时(MapStruct / Lombok) ↓ java -jar ↓ 启动时(Spring IOC 创建对象) ↓ 接口请求 ↓ 运行时(反射 / 业务逻辑)

七、现在回到最困惑的那一行

clazz.getDeclaredConstructor().newInstance();

1️⃣4️⃣ 它发生在什么时候?

答案非常明确:

运行时

1️⃣5️⃣ 为什么不能在编译时 new?

因为编译时:

  • ❌ 不知道用户项目里有什么类
  • ❌ 不知道哪些类加了 @Component
  • ❌ 不知道依赖关系

八、什么是 JVM?(先给“能用的理解”)

你现在不用理解 JVM 内存模型,只要知道一句话:

JVM = 执行 Java 字节码的“虚拟电脑”

它负责:

  • 加载 class
  • 创建对象
  • 执行方法
  • 回收内存

九、你现在应该“突然通了一点点”

你现在至少应该能区分:

阶段

能干什么

写代码时

写 class、注解

编译时

生成 class、生成代码

启动时

Spring 创建对象

运行时

调方法、反射

问题:为啥会存在编译时,如果没有点击编译能不能直接运行?

一、先回答这个最核心的问题

“为啥会存在编译时?如果我没有点击编译,能不能直接运行?”

结论先给你一句100% 正确的话

Java 不能不编译就运行

你所谓的“没点编译就能跑”,只是工具帮你偷偷编译了

二、从「人类」和「计算机」的矛盾开始讲

1️⃣ 计算机根本不认识你写的 Java

你写的代码:

System.out.println("Hello World");

在你眼里是:

打印一句话

但在计算机眼里是:

❌ 完全不认识


计算机只认识什么?

👉二进制

01001001 00101010 10101010 ...

所以问题来了:

❓ 那 Java 是怎么让计算机执行的?

答案就是两个字:

翻译

三、什么是「编译」?(非常重要)

1️⃣ 编译 = 翻译

编译器 = 翻译官

人类世界

计算机世界

Java 源代码

二进制指令

人写的

机器执行的

.java

.class

举个生活例子(一定要看)

你是中国人,去德国:

  • 你说:中文
  • 德国人听不懂
  • 必须有一个翻译

Java 世界完全一样:

你写 Java → JVM 听不懂 ↓ 编译器翻译 ↓ JVM 才能执行

2️⃣ Java 的「编译产物」是什么?

不是直接变成机器指令,而是:

字节码(bytecode)

.java →(javac 编译)→ .class

.class文件 ≠ 机器码
.class文件 =JVM 能看懂的“中间语言”

四、那 JVM 又是干嘛的?

1️⃣ JVM 是一个「虚拟计算机」

它干的事只有一件:

读取.class文件,并执行

所以完整链路是:

你写代码(.java) ↓ 编译(javac) ↓ .class 文件 ↓ JVM 执行

2️⃣ 为什么 Java 要多这一层?

因为:

一次编译,到处运行

  • Windows JVM
  • Linux JVM
  • Mac JVM

只要 JVM 存在,.class就能跑

五、那“我没点编译,程序咋就跑了?”

这是99% 新人都会误解的地方

真相是:

你“没有看到编译”,≠ “没有发生编译”

场景 1:IDEA 里点「Run」

IDEA 实际做了什么?

1. 自动保存代码 2. 自动调用 javac 编译 3. 自动启动 JVM 4. 把 .class 交给 JVM 执行

👉只是你没看见

场景 2:Spring Boot 启动

你点了:

Run Application

背后发生的是:

maven compile ↓ javac ↓ 生成 .class ↓ java -jar 启动 JVM

场景 3:命令行运行

你必须手动:

javac Main.java java Main

❗ 所以回答你那句话:

如果我没有点击编译能不能直接运行?

👉不能

只是:

IDE / Maven / Gradle 替你做了编译

六、什么是「写代码时 / 编译时 / 运行时」?

这是你后面理解IOC / 反射 / MapStruct / 注解处理器的钥匙。

1️⃣ 写代码时(Coding Time)

👉你在 IDEA 里敲代码

  • .java
  • 没有任何执行
  • 只是文本

📌 此时:

  • Spring 没启动
  • JVM 没启动
  • 程序根本不存在

2️⃣ 编译时(Compile Time)

👉javac 正在干活

它做什么?

  • 检查语法
  • 检查类型
  • 处理注解(非常重要⚠️)
  • 生成.class

📌MapStruct 就在这一步工作

3️⃣ 运行时(Runtime)

👉JVM 启动后

  • Spring IOC 在这里
  • Bean 创建在这里
  • 反射发生在这里
  • 方法调用在这里

用一句话记住:

阶段

是否有 JVM

写代码

编译时

运行时

七、为什么非要有「编译时」?

你问的是一个非常本质的问题

如果没有编译会怎样?

想象一下:

  • JVM 每执行一行 Java
  • 现场分析语法
  • 现场分析类型
  • 现场找错误

👉慢到爆炸

编译的本质价值:

把“复杂的检查和准备”,提前一次性做完

这样运行时:

  • 不用检查语法
  • 不用分析结构
  • 直接执行

八、这和 MapStruct 有什么关系?

MapStruct 的核心一句话

MapStruct 是“编译时”生成代码的工具

它不是运行时反射!

MapStruct 在哪一步干活?

👉编译时

javac 编译 ↓ 发现 @Mapper ↓ MapStruct 注解处理器介入 ↓ 生成 XxxMapperImpl.java ↓ 一起编译成 .class

这就是为什么:

  • MapStruct性能高
  • 没有反射
  • 调用是普通方法调用

IDEA 到底在偷偷干了什么

一、先给你一句“不绕弯”的结论

不是你写一行,IDEA 就真的帮你“编译一行”

但 IDEA 在“模拟编译器的工作”,实时帮你做检查

换句话说:

IDEA ≠ JVM

IDEA ≠ 真正的 javac

IDEA = 非常聪明的“语法/语义检查器”

二、你现在看到的“红色报错”到底是谁给的?

我们拆成三层来讲:

1️⃣ 你敲代码的那一刻,发生了什么?

你在 IDEA 里写:

int a = "hello";

你还没点 Run
你还没点 Compile
你甚至还没保存

👉但是已经红了

关键点:

此时,根本没有发生真正的“Java 编译”

2️⃣ 那是谁在报错?

👉是 IDEA 自己在报错

IDEA 内部有一套:

  • Java 语法解析器
  • 类型推导系统
  • 代码分析引擎(PSI)

它在做的是:

“假装自己是编译器,提前帮你看一眼”

用一句人话说:

IDEA 在你写代码时,一直在心里嘀咕:

“如果现在拿去给 javac 编译,会不会炸?”

3️⃣ 所以 IDEA 在做的事是:

行为

是否是真编译

红色波浪线

黄色警告

自动补全

Ctrl + B 跳转

提示类型不匹配

👉全都不是 javac

三、那什么才叫「真正的编译」?

只有这几种情况之一,才叫真正编译

✅ 情况 1:你点了「Build / Compile」

Build → Build Project

✅ 情况 2:你点了「Run」

IDEA 自动帮你做了:

javac 编译 ↓ 生成 .class ↓ 启动 JVM

✅ 情况 3:你用 Maven / Gradle

mvn compile mvn package

⚠️ 核心区分点

有没有生成.class文件

  • .class→ 真编译
  • .class→ 都是假象

四、那 IDEA 为啥能“像编译器一样聪明”?

这是一个非常关键的认知

1️⃣ IDEA 用的是「静态代码分析」

什么叫静态?

👉代码不运行,只看结构

它做的事情包括:

  • 解析语法树(AST)
  • 推断变量类型
  • 检查方法是否存在
  • 检查泛型是否匹配

举例:

List<String> list = new ArrayList<>(); list.add(123);

IDEA 能立刻告诉你:

❌ 你加了 Integer,但 List 里是 String

2️⃣ 但 IDEA 做不到什么?

做不到

Object obj = getSomething(); obj.doSomething();

如果:

  • getSomething()是运行时才决定的
  • 用了反射
  • 用了泛型擦除后的类型

👉 IDEA可能不报错,但运行时会炸

3️⃣ 所以你要记住一句话(非常重要)

IDEA 只管“像不像能编译”

javac 决定“能不能编译”

JVM 决定“能不能跑”

五、那为什么“写一半代码也能红”?

因为 IDEA 在做:

“不完整代码的容错分析”

例如你刚写:

public class A { public void test(

这是不完整代码
javac 一定会报错

但 IDEA 仍然:

  • 尽量帮你解析
  • 尽量给你补全
  • 尽量提示你下一步

六、所以现在我们把“时间轴”重新画一遍

你在 IDEA 写代码 ↓ IDEA 实时分析(假编译) ↓ 你点击 Run / Build ↓ 真正 javac 编译(编译时) ↓ 生成 .class ↓ JVM 启动(运行时)
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/19 9:29:14

PX4模块设计之三十四:ControlAllocator模块的混控机制解析

1. ControlAllocator模块的核心作用 ControlAllocator是PX4飞控系统中承上启下的关键模块&#xff0c;它就像一位经验丰富的交通指挥员。当姿态控制器发出"向左转"或"加速上升"这类抽象指令时&#xff0c;ControlAllocator需要将这些指令翻译成每个电机/舵…

作者头像 李华
网站建设 2026/4/17 14:31:51

5倍效率提升:企业级系统自动化部署的零失误解决方案

5倍效率提升&#xff1a;企业级系统自动化部署的零失误解决方案 【免费下载链接】ubuntu-autoinstall-generator Generate a fully-automated Ubuntu ISO for unattended installations. 项目地址: https://gitcode.com/gh_mirrors/ub/ubuntu-autoinstall-generator 当您…

作者头像 李华
网站建设 2026/4/18 7:14:16

5大智能解锁技术指南:信息获取工具核心原理与实战应用

5大智能解锁技术指南&#xff1a;信息获取工具核心原理与实战应用 【免费下载链接】bypass-paywalls-chrome-clean 项目地址: https://gitcode.com/GitHub_Trending/by/bypass-paywalls-chrome-clean 在信息爆炸的今天&#xff0c;科研工作者、金融分析师和内容创作者常…

作者头像 李华
网站建设 2026/4/18 15:51:37

Cherry.Studio 系统提示词入门指南:从零构建高效提示词工程

背景介绍&#xff1a;为什么提示词工程成了刚需 第一次把大模型接进业务&#xff0c;我满脑子都是“它那么聪明&#xff0c;应该能猜到我想要什么”。结果 AI 回我一句“抱歉&#xff0c;我无法理解您的需求”。那一刻我才意识到&#xff1a;模型再强&#xff0c;也读不了空气…

作者头像 李华