IDEA 实战:第一个 Java 工程与编译运行全流程
IDEA 不是「带高亮的记事本」。它是一个替你按顺序做完所有机械动作的机器:你保存文件,它编译;你改了依赖,它去仓库取货;你敲下 Run,它把 .java 变成 .class、拼好 classpath、启动 JVM、调用 main。这一篇讲三件事:怎么装并认路(界面与六个名词)、怎么跑起来(项目结构 / SDK / 运行配置)、怎么在它骗你的时候识破它(缓存、编码、红字、Run 按钮变灰)。
不用 IDE 写 Java,就像用真笔写稿却指望印刷厂自动看懂你的手稿——你改了三页内容,印刷厂手里还是上一版铅字,印出来的报纸照旧。IDEA 干的就是「改稿后重新排版印刷」这一步:每次 Run 之前先增量重排(编译)改动过的那几页,再把成品交给读者(JVM)。理解了这一点,「代码明明改了、跑出来还是旧的」这类怪事就一眼见底。

学完这一篇,你应该能回答:
- Project / Module / SDK / Artifact 分别是什么?谁决定我用哪个 JDK?
- 我点了 Run,IDEA 到底先做了什么、再做了什么?产物写到哪个目录?
- 为什么代码全红不一定是我的错?为什么 Run 按钮会突然变灰?
IntelliJ IDEA 是全球 Java 开发者使用率最高的 IDE。它有两个版本,选错会让后面的学习无故多绕几个弯:
| 对比项 | Community(社区版) | Ultimate(旗舰版) |
|---|---|---|
| 价格 | 免费 | 付费(有试用与教育授权) |
| 纯 Java / Maven / Gradle | 支持 | 支持 |
| Spring / Spring Boot 支持 | 无(需装插件) | 内置完整支持 |
| 数据库工具、HTTP Client | 无 | 内置 |
| Web(Servlet / JSP / Thymeleaf) | 无 | 内置 |
| 适用人群 | 学 Java 基础、写纯 Java 项目 | 做 Spring 企业开发 |
结论很直接:本教程后面的内容涉及大量 Spring 开发,建议用 Ultimate;如果暂时只学 Java 语法,Community 完全够用。
IDEA 自带官方中文语言包(Chinese Language Pack)。切换方式:Settings → Plugins 搜索 Chinese 安装后重启。给个实在的建议:
- 初学阶段可以切中文,能显著降低「找不到菜单」带来的挫败感
- 但快捷键、报错信息、Stack Overflow 上的解决方案都是英文,长期看英文界面收益更大
- 折中方案:界面上手用中文,遇到陌生概念立刻对照英文菜单名记下来
无论中英文界面,命令面板都是 Ctrl+Shift+A(Mac 是 Cmd+Shift+A)。忘了功能在哪个菜单,直接输入英文名搜索,比翻菜单快十倍。
新手打开 IDEA 常常被 Project Structure 里的一堆名词绕晕。它们其实是「从大到小、从容器到产物」的一条链:
| 名词 | 中文 | 一句话解释 | 生活类比 |
|---|---|---|---|
| Project | 项目 | 顶级容器,管理一组模块与配置 | 一栋大楼 |
| Module | 模块 | 实际承载源码的单元,可有多个 | 楼里的每一户 |
| SDK | 软件开发工具包 | 这里指项目使用的 JDK | 每户用的水电标准 |
| Library | 库 | 外部依赖的 jar 集合 | 家里添置的电器 |
| Facet | 框架支持 | 标记模块属于哪种技术(如 Web) | 给房间标注用途 |
| Artifact | 构建产物 | 打包后的 jar/war 及其输出位置 | 装修完拿到的成品 |
关系一句话概括:一个 Project 可以含多个 Module,每个 Module 绑定一个 SDK、引用若干 Library、可挂 Facet,最终产出 Artifact。
新建项目后,根目录会多出一个 .idea/ 文件夹和一个 *.iml 文件,里面存的是:
.idea/├── workspace.xml # 窗口布局、最近打开的文件、运行临时状态├── modules.xml # 模块清单├── misc.xml # 项目级 JDK 配置(这个常常需要共享)└── *.iml # 模块定义(JDK、依赖、输出目录)它们该不该提交到 Git?没有统一答案,取决于内容:
workspace.xml存的是个人窗口状态,必须排除,提交了会天天冲突misc.xml/*.iml里可能包含 JDK 版本、模块依赖,团队统一时可以提交- 更省心的做法:
.gitignore排除整个.idea/,让每个人都由 Maven 的pom.xml重新生成
想「提交一部分、忽略一部分」,就在 .gitignore 里写 .idea/* 再用 !.idea/misc.xml 单独放行——忽略整个目录、单独白名单,比逐条排除更好维护。
这些名词和动作 IDEA 从不解释,但每一个都对应一件具体的事。玩一局配对:左边是你在菜单里点的东西,右边是它真正做的事——配错会当场告诉你差在哪:

按向导走一遍:File → New → Project,语言选 Java,构建系统选 IntelliJ(先不上 Maven,减少变量),在 JDK 下拉框里选 17 或 21——如果下拉框是空的,说明还没装 JDK,点 Add SDK → Download JDK 让 IDEA 帮你下载。
创建完成后,在 src 目录上右键,依次 New → Package(填 com.example.demo)、在包上 New → Java Class(填 Hello),然后写入:
package com.example.demo;public class Hello { public static void main(String[] args) { // psvm 是 IDEA 的实时模板:输入 psvm 回车即生成这一行 String name = "Spring"; int year = 2024; System.out.println("Hello, " + name + "!"); System.out.printf("Spring Framework 诞生于 %d 年%n", 2003); System.out.println("当前学习年份:" + year); }}写完后,代码行号左侧会出现绿色小三角,点击它选 Run 'Hello.main()',或者直接按 Shift+F10。下方的 Run 窗口会打印出结果。
点第一次 Run 时,IDEA 自动替你创建了一个「运行配置」(Run/Debug Configuration),它记录了「怎么跑这个类」。打开 Run → Edit Configurations 能看到这些关键项:
| 配置项 | 作用 | 新手常见误用 |
|---|---|---|
| Main class | 从哪个类的 main 启动 | 选错类导致「找不到 main」 |
| Program arguments | 传给 String[] args 的参数 | 与 VM options 填反 |
| VM options | 传给 JVM 的参数,如 -Xmx512m | 把 -D 系统属性写进 args |
| Working directory | 程序的工作目录 | 读相对路径文件时找不到文件 |
| Use classpath of module | 用哪个模块的 classpath | 多模块下选错模块 |
Program arguments 给的是你的程序,VM options 给的是JVM。两者填反是高频事故:把 --spring.profiles.active=dev 填进 VM options 会导致它被当成 JVM 参数而启动失败。
很多新手以为「Run 就是运行 Java」,其实 IDEA 在背后先干完了「编译」这步。完整链路是:
- 增量编译:IDEA 只重编你改动过的那些
.java文件,而不是全量重来,所以第二次运行总是很快 - 落地字节码:编译产物写进输出目录,非 Maven 项目是
out/,Maven 项目是target/classes - 类加载:启动 JVM,由 ClassLoader 读入主类字节码
- 执行 main:JVM 调用入口方法,程序开始运行
改稿后要重新印刷。你手里的稿纸(.java)改了,但读者拿到的报纸(.class)还是上一版铅字印的——不在同一张桌上比版本,你永远看不出问题。IDEA 的增量编译就是「只重排改动过的那几页」,所以快;而 Rebuild Project 是全部重新排版,怀疑铅字箱本身脏了才用。这条类比同时解释了第七节那两个坑:「改了代码不生效」和「删了 out 目录后类找不到」。
这是最容易被混淆的一对目录,一定要分清:
| 对比项 | out/(IntelliJ 构建) | target/(Maven 构建) |
|---|---|---|
| 谁生成 | IDEA 自带的构建器 | Maven 插件 |
| 触发方式 | Build Project / Run | mvn compile / mvn package |
| 目录结构 | out/production/<模块名>/ | target/classes/ |
| 是否可删 | 可删,重启即重建 | 可删,mvn clean 清空 |
| 常见坑 | 删了 out 却没重编 → 类找不到 | 改了代码没 clean → 跑的是旧的 |
上面那张表的第六行「跑的是旧的」最难自己发现。这段动画把两份字节码怎么并存演了一遍——注意第 5 帧:Run 和 java 命令读的可以不是同一份:

构建这件事在 IDEA 里还藏着一个真数字:它自己的构建器跑在独立进程里,默认只给 700 MiB。项目一大、注解处理器一多,构建输出里就会出现那行 java.lang.OutOfMemoryError: Java heap space——注意它崩在构建阶段,你的程序本身跑得好好的。把这个数字拖一遍:
- 课堂示例、一两个模块的项目碰不到上限
- 撞上限时的症状在构建输出里:java.lang.OutOfMemoryError: Java heap space
- 崩的是构建,不是运行时——Run 起来的程序一切正常,所以很容易怀疑错方向
- 别急着重启电脑,这个数字就是为这一格准备的
Build Project 与 Rebuild 的区别同样值得记住:
Build Project(Ctrl+F9):增量构建,只编译有变化的文件——平时用这个Rebuild Project:先清空所有输出再全量重编——怀疑「缓存不一致」时才用,慢但干净
明明改了代码,运行结果却还是旧的,九成是增量构建的缓存没更新。此时 Build → Rebuild Project 一次就能解决,别急着重启电脑。
把本节开头那四步链路摊开成一次单步执行。左边是按下 Run 之后依次发生的六件事,右边同步刷新「此刻的变量」和「谁在调用谁」——重点看第 2 步和第 4 步,第十一节那个灰色按钮和第十二节那条 程序包不存在,一个出在第 2 步,一个出在第 4 步:
点击绿色三角 Run # 先取 Run/Debug ConfigurationIDEA 校验:SDK / 模块 / 有没有 main # 任一项不合格,按钮就是灰的增量编译改动过的 .java # 写进 out/production 或 target/classes拼 classpath:模块依赖 + 库 jar # Use classpath of module 决定内容fork 一个新 JVM:java -cp ... Hello # IDEA 到这里就退场了类加载 → 调用 Hello.main(String[]) # 你的代码终于开始跑| 配置来自 | Run → Edit Configurations |
| 已有配置 | Hello.main() |
| 第一次点时会怎样 | 自动新建一份 |
点击 Run调试(Debug)才是 IDEA 真正的生产力引擎。按 Shift+F9 以 Debug 模式启动,效果和 Run 一样,只是会在断点处停下来。
先在想要观察的那一行行号左侧单击,出现红色圆点就是断点打好了。然后记住下面这组操作:
public static int sum(int[] nums) { int total = 0; for (int i = 0; i < nums.length; i++) { total += nums[i]; // ← 在这行打条件断点:i == 3 } return total;}- 条件断点:在断点上右键,Condition 填
i == 3,只在满足条件时停下——循环第一千次时尤其救命 - Step Over(F8):执行当前行,遇到方法调用不进去
- Step Into(F7):进入被调用的方法内部
- Step Out(Shift+F8):从当前方法里跳回调用它的那一层
- Evaluate Expression(Alt+F8):弹出式计算器,实时算任意表达式,如
nums.length - Watches:把变量加进监视列表,每次停下都能看到它的最新值
还有一招很少人用却极其好用:停下时可以直接在 Variables 面板里双击变量、回车改值,然后继续走(Resume)。想验证「如果这个参数是空会怎样」,不必改代码重跑,改一下值即可。
调试多线程时别用 Step Over 硬跟——线程会乱跳。改用断点上的 Suspend: Thread 设置,并给断点加个日志输出(Breakpoint → More → Evaluate and log),既不阻塞线程又能打印轨迹。
真实项目几乎都是 Maven 工程。打开方式:File → Open 直接选 pom.xml 所在的目录,IDEA 会自动识别为 Maven 项目并开始导入。
导入后,右侧会出现 Maven 工具窗口。几个高频动作要牢记:
- 依赖自动同步:
pom.xml一改,右上角弹出小图标提示Reload,点一下就把新依赖拉下来 - Reload All Maven Projects:Maven 面板左上角的刷新按钮,等价于重读全部 pom 重新解析依赖
- 黄标提示:依赖名下面画黄色波浪线,通常表示「这个 artifact 不在本地仓库」或「版本被 dependencyManagement 覆盖」,鼠标悬停有说明
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <!-- 黄标常见原因:父 POM 已用 dependencyManagement 管理版本,这里无需再写 version --></dependency>坑:IDEA 里代码全红、但 mvn clean package 明明能成功,多半是 IDEA 的 Maven 索引坏了。执行 Maven 面板 → Reload All Maven Projects;还不行就 File → Invalidate Caches → Invalidate and Restart。永远以命令行的构建结果为准,IDEA 的红只是它自己的视图。
反过来也要会看:File → New → Project 向导里勾的那些复选框,最后都会变成 pom 里的 <dependency>。勾一遍再对照生成物,你就知道 IDEA 到底替你写了什么——下次它不替你写的时候,你能自己补上:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.4</version> <!-- 版本由 BOM 统管,子依赖不写 version -->
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>demo-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>17</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>| 现象 | 根因 | 解决 |
|---|---|---|
| 所有 Java 类报红、无法运行 | 项目 SDK 未配置 | File → Project Structure → SDK 选一个 JDK |
输出中文全是乱码 锟斤拷 | 文件编码为 GBK,与 UTF-8 不一致 | Settings → File Encodings 全部设为 UTF-8 |
package xxx does not correspond to the file path | 包名与目录路径不一致 | 右键 Source Root 设为 src,或修正包名 |
| 改了代码死活不生效 | 旧缓存 / 旧输出 | Invalidate Caches and Restart 或 Rebuild |
Lombok 的 @Data 编译不报错但取不到 getter | 没装 Lombok 插件 | Plugins 里搜 Lombok 安装并开启注解处理 |
启动报 Port 8080 was already in use | 上一个进程没退干净 | 结束占用进程,或改端口 |
定位「端口占用」的最快方式,是一条命令:
# Windows:看看是谁占用了 8080netstat -ano | findstr :8080# macOS / Linuxlsof -i :8080- 输出最后那列的数字就是进程 PID,再用任务管理器或
taskkill /PID <pid> /F结束它 - 别急着重启电脑——那样只是掩盖问题,下次还会遇到
警告:Settings → File Encodings 只改当前项目,建议同时把 Project Encoding、Default encoding for properties files 都设为 UTF-8,并勾选 Transparent native-to-ascii conversion,否则 application.properties 里的中文注释仍会乱码。
| 功能 | Windows | macOS |
|---|---|---|
| 运行 / 调试 | Shift+F10 / Shift+F9 | Ctrl+R / Ctrl+D |
| 构建项目 | Ctrl+F9 | Cmd+F9 |
| 任意搜索(命令面板) | Ctrl+Shift+A | Cmd+Shift+A |
| 全局搜索文件 / 类 | Ctrl+Shift+N | Cmd+Shift+O |
| 生成代码(getter、构造器) | Alt+Insert | Cmd+N |
| 重命名(安全重构) | Shift+F6 | Shift+F6 |
| 格式化代码 | Ctrl+Alt+L | Cmd+Opt+L |
| 查看定义 / 实现 | Ctrl+B / Ctrl+Alt+B | Cmd+B / Cmd+Opt+B |
| 单步调试 | F8 / F7 | F8 / F7 |
| 万能 Alt 键(多光标、列选择) | 按住 Alt 拖动 | 按住 Opt 拖动 |
不要一次背完。先把「运行、调试、命令面板、全局搜索、生成代码」这五个练成肌肉记忆,日常效率就能翻倍,其余用到再查。
Windows 上 Shift+F10 最常见的冲突对象是 NVIDIA 显卡驱动的全局热键(打开控制面板),其次是输入法与截图工具。症状很有辨识度:按下去弹的不是 IDEA 的 Run 窗口,而是别的东西,甚至什么都不弹。两种修法任选其一:Settings → Keymap 搜 Run… 改成 Ctrl+Shift+F10;或到显卡控制面板里关掉那条热键。判断是不是快捷键问题,先用鼠标点行号旁的绿三角——能跑就说明配置本身没坏。
第一个实验就是第四节的动画版:保存之后到进程启动之间,IDEA 一共插了几步。切「编译产物」看 target/classes 怎么被填;切「热重载」看改一行文案为什么不用重启;切「断点调试」看第五节那些动作在进程里对应什么:
第二个实验回答一个更根本的问题:JVM 是怎么把你的类拿进内存的。「类加载」这一步会显示它按全限定名(com.example.demo.Hello)去找文件——这就是第十二节那条 Package ... does not correspond to the file path 报错的真正由来:包名不是装饰,它是路径的一部分。
第三个实验专治「代码没写错却报找不到类」。选「ClassNotFoundException」,你会看到它在 classpath 上逐个目录翻找;只要 target/classes 是空的或过期,任何一句 java 命令都会走到这条死路:
第四个实验是给下一篇铺路的:Spring Boot 应用的启动序列比裸 main 多了好几步。Runner 是 Boot 留给你的「启动后要做点什么」的接口(CommandLineRunner / ApplicationRunner),最后一个实验则演示启动失败时控制台那一大坨该怎么从上往下读:
第五个实验治的是本篇最窝囊的一类问题:「IDE 里能跑,命令行不能跑」——两边用的根本不是同一个 JDK。切「谁说了算」看终端怎么按 PATH 顺序挑,切「装了好几个版本」看 IDEA 的 Project SDK 和终端的 java 怎么各奔东西:
实验做到这里,可以换成自己敲。下面这台控制台连着浏览器里的同一个内核,回显全部由内核算出来——先敲 lab idebuild build,再按顺序往下:
lab idebuild run 和 lab idebuild debug 连着敲最省话——两条输出只差一个 JVM 参数。第五节那六个调试动作之所以能停下来,全在那一条参数上。
顺手记住这张对照图。左边六个动作是新手每天都在做的,右边是同一件事的正确姿势——差别不在效率,而在你会不会被工具骗:

Run 按钮(绿色三角)变灰从来不是「IDEA 坏了」,而是它判定「现在按下必然失败」。左边选模块状态,右边选 JDK 状态,面板直接给出该点哪里恢复:


无匹配结果
沙盘里 no-main 那一格最容易被忽略——IDEA 只给「它认得的入口」画绿三角。main 的签名是硬性约定:public、static、void、参数 String[],四个条件少一个都不行。
| 报错原文(片段) | 真实原因 | 30 秒自救 | 深挖看第几篇 | |
|---|---|---|---|---|
Class 'Hello' is public, should be declared in a file named 'Hello.java' | 公共类名与文件名不一致(大小写也算不一致) | 改文件名,别改类名;两者必须逐字符相同 | #1 第四节 | |
Package com.example.demo does not correspond to the file path 'com/example/hello' / does not match its package | 目录大小写与包名不符,或 src 没标成 Sources Root | 右键该目录 → Mark Directory as → Sources Root,再核对包名层级 | 本篇第二节 · 上方沙盘 | |
Exception in thread "main" java.lang.ClassNotFoundException: com.example.demo.Hello(命令行里报,IDEA 里正常) | target/classes 根本没编译过,或你手敲的 -cp 不含输出目录 | 先 mvn compile(或 IDEA Ctrl+F9),再 java -cp target/classes com.example.demo.Hello | #2 Maven 生命周期 | |
java: 程序包 xxx 不存在 / Cannot resolve symbol 'springframework' | pom 改了但没 Reload,依赖没进模块 classpath | Maven 面板 → Reload All Maven Projects;仍不行 File → Invalidate Caches | 本篇第六节 | |
| Run / Debug 按钮灰色不可点 | 没配 Project SDK、认不出 main、或模块未标 Sources Root | 按第十一节沙盘三选一排查;最常见是 Project Structure → SDK | 本篇第十一节 | |
Shift+F10 触发的是系统全局快捷键而不是 IDEA 的运行 | 与其他软件抢键(输入法、显卡驱动、截图工具最常见) | Settings → Keymap 搜 Run 重新指定;或先用鼠标点绿三角确认配置本身没问题 | 本篇第八节的抢键说明 | |
控制台中文乱码 锟斤拷 / ?????? | 源文件编码、编译器 -encoding、控制台字符集三者不一致 | Settings → File Encodings 全设 UTF-8;运行时加 -Dfile.encoding=UTF-8 | #35 日志体系 | |
Port 8080 was already in use | 上一次启动的进程还活着,占着端口 | `netstat -ano \ | findstr :8080 取 PID,taskkill /PID <pid> /F` | 本篇第七节 |
ClassNotFoundException 在 IDEA 里几乎见不到、在命令行里天天见——因为 IDEA 用的是自己的构建输出(可能是 out/production/...),而你手敲的命令默认指向 target/classes。两套目录不同步是这类「同一个类有时找得到有时找不到」的根源。
这条坑值得用一段真堆栈收尾。注意凶手不在最上面那行,也不在 Exception in thread 那句里——点给你看:
你在 IDEA 里 Ctrl+F9 编过、Run 也正常;照上表最后一条敲 java -cp target/classes com.example.demo.Hello,直接抛异常。
目标:亲手制造并修好本篇最常见的三个「IDE 骗你」现场。
package com.example.demo;public class DebugLab { public static int sum(int[] nums) { int total = 0; for (int i = 0; i < nums.length; i++) { total += nums[i]; // ← 在这里打断点,条件设 i == 3 } return total; } public static void main(String[] args) { int[] data = {1, 2, 3, 4, 5, 6}; int result = sum(data); System.out.println("sum = " + result); // ← 在这行打断点,停下时把 result 改成 0 System.out.println("result * 2 = " + (result * 2)); }}按顺序做完这三件事,并各写一句话记录现象:
- 在第 8 行打条件断点
i == 3,用Shift+F9启动,确认只在第四次循环停住。 - 停在第 15 行时,在 Variables 面板双击
result改成0,再 Resume。预期输出:第二行打印result * 2 = 0——证明改变量真的改变了执行结果。 - 用
Evaluate Expression(Alt+F8)在不改代码的前提下算出data.length + result,然后把nums[0]输入进去,观察它抛出的异常类型。
验收清单:你能说出「条件断点为什么比 println 快」,以及「改变量值和改代码重跑的本质区别」。
三个小改动,各自复现一类高频故障,练的是「一眼看出根目录在哪」:
- 把
package com.example.demo;留着,但把文件移动到src根下。你会观察到 IDEA 报包名与路径不符,且第十节那个类加载实验里「全限定名 → 磁盘路径」的映射当场断裂。 - 删掉整个
out或target目录,然后不要 Build,直接从终端跑java -cp target/classes com.example.demo.DebugLab。你会观察到ClassNotFoundException;补一次mvn compile或Ctrl+F9立刻恢复正常。 - 把
Settings → Appearance & Behavior → System Settings里的自动保存关掉,改一行打印但不按Ctrl+S就点 Run。你会观察到 IDEA 弹出的那条提示,以及它为什么会先把改动同步到磁盘再编译。
提示:做完第 3 条,你就理解了「保存 ≠ 编译 ≠ 运行」是三件独立的事。
做一个 双模块 Maven 工程,把本篇和 #2 的知识串起来:
lab-ide/ ← 父 pom,packaging=pom├── lab-core/ ← 放 SumUtil 与一个自定义异常└── lab-app/ ← 依赖 lab-core,含 main 与一个 CommandLineRunner要求:① 用 File → Open 打开父目录导入(不要 New Project),确认 Maven 面板出现两个模块;② lab-app 的 main 里故意留一处空指针,用异常断点(Run → View Breakpoints → Java Exception Breakpoints)让 IDEA 在抛出那一刻自动停住,而不是等你逐行找;③ 配一个 CommandLineRunner,在启动后打印一行统计信息;④ 分别用 Run 和 Debug 各跑一次,写下两者的三条差异;⑤ 最后从终端用 java -cp 手动跑一次,体会 IDEA 替你拼了什么。
验收清单:mvn clean install 全绿;IDEA 里 Debug 能在异常发生处停住;终端手动 java -cp 也能跑通——这说明你真的知道 classpath 是怎么拼出来的。
Project / Module / SDK / Artifact 四个词,哪个决定「用哪个 JDK」,哪个决定「打包成什么」?
out/production/<模块> 和 target/classes 谁生成的?为什么它们会不同步?
Run 与 Debug 走的链条只差哪一步?这一步带来了什么能力、什么代价?
Program arguments 和 VM options 分别交给谁?把 --spring.profiles.active=dev 填错格子会怎样?
IDEA 里代码全红而 mvn clean package 成功,该信谁?为什么?
保存归磁盘、编译归字节码、运行归 classpath、调试归断点——四件事各有各的开关,出问题先问自己在哪一层。
这一节把 IDEA 的三条主线理顺了——结构(Project / Module / SDK 的分层关系)、运行(增量编译写进 out/ 或 target/,JVM 加载再执行 main)、调试(断点、单步、求值、改变量值)。再加上绕开六个新手坑,你的开发环境从此稳定可用,可以专心写代码了。