Skip to content

Markdown 与文档习惯 ​

S0-007建议学入门约 30 分钟JDK 21学习准备与环境 · 工程工具

1. 本节定位 ​

Markdown 是技术工作的通用书写格式:README、Issue、Pull Request 描述、代码注释、技术笔记、本知识库的全部内容,都用它。

本节不只讲语法(语法十分钟就能学完),重点讲技术文档的书写习惯——写什么、不写什么、怎么让三个月后的自己看得懂。

2. 学习目标 ​

完成本节后,你应该能够:

  • 熟练使用标题、列表、代码块、表格、链接、任务列表;
  • 用固定模板记录一个 Bug(现象 / 复现 / 定位 / 修复 / 验证);
  • 用固定模板记录一节学习笔记;
  • 判断一份笔记是"能复用"还是"三个月后自己也看不懂"。

3. 前置知识检查 ​

无。会打字就能开始。

4. 为什么需要这个知识 ​

技术文档有两个消费者:别人和三个月后的你自己。

只写给自己看时,人往往会写成这样:

text
今天搞了半天,那个空指针终于好了,是因为 map 里没有那个 key。

一个问题:三个月后你还记得是哪个 map、哪个 key、改了什么吗? 而且这个笔记搜不到——你搜索"NullPointerException"匹配不上这句话(因为当时你写的是"空指针")。

再看一份能复用的版本:

markdown
## 现象
查询用户详情接口偶发 NPE,订单列表页刷新 10 次出现 1 次。

## 原因
`UserService.getDetail` 里 `map.get(userId)` 返回 null,直接调用了 `.getName()`。

## 修复
改用 `Optional.ofNullable(...).map(...)`,并在接口层返回 404 而不是 500。

## 验证
补充 3 个单元测试(key 不存在 / value 为 null / 正常),接口回归 20 次无异常。

差别不在文采,而在结构:现象、原因、修复、验证四段固定,写的人不用想"该怎么记",看的人能直接跳到关心的段落。

5. 核心概念 ​

5.1 必备语法(够用即可) ​

markdown
# 一级标题(一篇文档只用一个)
## 二级标题

- 无序列表
1. 有序列表
- [ ] 待办项
- [x] 已完成项

`行内代码` 与**加粗**、*斜体*

> 引用:常用于强调结论或引用规范

```java
// 代码块一定要写语言,这样才有语法高亮
System.out.println("Hello");
```

| 列 | 说明 |
| --- | --- |
| 表格 | 对比信息时最清楚 |

[链接文字](https://example.com)

5.2 技术笔记的四个要素 ​

要素作用判断标准
结论先行让人三秒知道结果开头一段能不能独立看懂
可搜索的关键词未来能找到它是否包含异常类名、方法名、错误码
可执行的步骤别人能复现是否写了命令、参数、环境
自己的判断体现你理解了有没有"为什么这么修"而不是只抄命令

5.3 不要做的事 ​

反模式问题
截图代替文字不可搜索、不可复制、不可 diff
整段粘贴日志关键信息被淹没,应节选 + 标注
只贴解决方案不写问题三个月后不知道它在解决什么
标题层级乱跳(# 直接到 ####)目录结构错乱,读者迷路
代码块不写语言没有高亮,阅读成本上升

5.4 本知识库的文档约定 ​

你正在读的每节课都遵循同一套结构,这就是"文档模板"的价值:结构固定后,注意力就能放在内容上。

text
本节定位 → 学习目标 → 前置知识检查 → 为什么需要 → 核心概念
→ 递进示例 → 完整可运行代码 → Debug 观察点 → 常见错误
→ 动手实验 → 练习题 → 参考答案 → 掌握标准 → 扩展资源 → 下一步

6. 递进示例 ​

6.1 最小示例:学习笔记模板 ​

markdown
# S1-017 HashMap 学习笔记

## 一句话结论
HashMap 用数组 + 链表/红黑树实现,查找平均 O(1);扩容阈值 = 容量 × 0.75。

## 我踩的坑
自定义对象做 key 时没重写 equals/hashCode,`get` 永远返回 null。

## 关键代码
```java
record GoodKey(String id) {}   // record 自动生成 equals/hashCode

还没搞懂 ​

红黑树化的阈值为什么是 8 和 6(记下来,学到 JVM 时回看)


最后一段"还没搞懂"是关键——**把疑问显性记录下来**,比假装都懂了有价值得多。

### 6.2 业务示例:Bug 记录模板

```markdown
## 环境
JDK 21 / Spring Boot 3.2 / MySQL 8

## 现象
并发提交订单时,偶发 `Duplicate entry` 主键冲突。

## 复现步骤
1. 用 JMeter 以 50 并发调用 `/order`
2. 观察数据库日志,约 1% 请求报主键冲突

## 定位过程
查看主键生成逻辑,发现用的是"查最大 ID + 1"而非数据库自增/序列。

## 根因
并发下两个请求查到同一个最大 ID,各自 +1 后写入,撞车。

## 修复与验证
改用分布式 ID 生成器;补充并发测试用例(50 并发 1000 次请求无冲突)。

这份记录的价值不在"修复了 bug",而在于下次遇到类似现象时能 5 秒定位。

6.3 反例:只有结果没有过程的笔记 ​

text
今天学了 Stream,挺好用的,filter 和 map 都试了一下。

三个月后你要用它时,这份笔记提供不了任何信息——没有 API 清单、没有代码、没有坑点、没有适用场景。

7. 完整可运行代码 ​

本节无 Java 代码。作为替代,请把下面这份模板保存到你的笔记工具里,作为以后写 Bug 记录的标准骨架:

markdown
## 现象
(一句话说清"什么操作 → 什么结果",包含完整异常类名便于搜索)

## 影响范围
(哪些功能、多少用户、是否阻塞)

## 复现步骤
1. 环境:
2. 操作:
3. 期望结果:
4. 实际结果:

## 定位过程
(用过什么命令、看了哪些日志、排除了哪些可能)

## 根因
(一句话结论 + 关键代码片段)

## 修复与验证
(改了什么、怎么验证、补了什么测试)

8. Debug 观察点 ​

没有调试器可开,但有一个判断练习:打开你半年内写过的一份笔记,只看前 30 秒,问自己三个问题:

  1. 我知道这份笔记在解决什么问题吗?
  2. 里面的命令我现在能直接复制执行吗?
  3. 如果同事遇到同样的报错,我敢把这份笔记发给他吗?

三个都是"是",说明你的文档习惯已经合格。

9. 常见错误 ​

错误 1:把 IDE 的红色波浪线当真——在 Markdown 里写代码块忘了语言标记 ​

text
```
List<String> list = new ArrayList<>();
```

没有语言标记就没有高亮。修复:写成 ```java。

错误 2:标题层级跳跃 ​

markdown
# 标题
#### 直接跳到四级

修复:逐级递进(# → ## → ###),否则生成的目录会错乱。

错误 3:表格里包含 | 字符没转义 ​

单元格内容里的 | 会被当成列分隔符。修复:写成 \|,或用行内代码包起来。

10. 动手实验 ​

目标:产出两份可复用的文档。

步骤:

  1. 为你最近解决的一个问题(工作或学习中的都可以)写一份 Bug 记录,用第 7 节的模板;
  2. 为 S1-005 类与对象 写一份学习笔记,用第 6.1 节的模板,必须包含"还没搞懂"一节;
  3. 把两份文档放进一个 Git 仓库(可以就是本项目的一个分支),提交格式用 docs: ...;
  4. 三天后回来读一遍,看能不能在不看原资料的情况下理解。

验收方式:第 4 步能读懂,说明记录合格。

扩展任务:给笔记加一个"关键词行"(如 #NullPointerException #HashMap #并发),方便日后搜索——这是很多人的笔记"写得多但找不到"的原因。

11. 练习题 ​

基础题

  1. 判断:Markdown 里标题可以从 # 直接跳到 ####。(对 / 错)
  2. 填空:GitHub 风格的任务列表写作 ______。
  3. 简答:技术笔记的四个要素是什么?

改写题

  1. 把下面这句口语化记录改写成可复用的笔记片段:
text
今天用 for-each 删 list 里的元素报错了,后来换了 removeIf 就好了。

综合任务

  1. 为本知识库写一份"我的学习环境说明":包含 JDK 版本、IDE、Maven 镜像配置、常用命令。要求:
    • 用 Markdown 组织,含至少一个表格;
    • 包含可复制执行的命令;
    • 能在别人(或未来的你)换一台电脑时照着搭好环境。
分级提示

提示 1(方向):第 4 题的关键是把"报错"变成"完整异常类名 + 代码行 + 原因 + 修复"。

提示 2(关键点):第 5 题可以直接借鉴 S0-002 IDEA 与项目创建 里的环境检查清单。

提示 3(接近答案):第 4 题的合格答案里应该出现 ConcurrentModificationException 这个完整类名——因为半年后你是靠它搜索的。

12. 参考答案 ​

基础题
  1. 错。应逐级递进,否则文档目录结构会错乱。
  2. - [ ] 未完成 与 - [x] 已完成。
  3. 结论先行、可搜索的关键词、可执行的步骤、自己的判断。
改写题(第 4 题)
markdown
## 现象
遍历 `ArrayList` 时调用 `list.remove(item)`,抛出 `ConcurrentModificationException`。

## 原因
for-each 底层使用迭代器,遍历过程中直接修改集合会让迭代器检查失败。

## 修复
1. 用 `list.removeIf(item -> 条件)`;
2. 或改用显式 `Iterator` 并调用 `iterator.remove()`。

## 注意
删除倒数第二个元素时可能不抛异常(迭代已结束,没有机会检查),所以这个 bug 容易偶发。

关键改进:写上了完整异常类名(可搜索)、触发条件(可判断是否同因)、两种修复方案。

综合任务(第 5 题)

参考结构:

markdown
# 我的 Java 学习环境

| 项目 | 版本 / 位置 |
| --- | --- |
| 操作系统 | Windows 11 |
| JDK | OpenJDK 25.0.2 LTS(Microsoft) |
| JAVA_HOME | C:\Program Files\Microsoft\jdk-25.0.2.10-hotspot |
| 编译目标 | Java 21(`--release 21`) |
| IDE | IntelliJ IDEA Community |
| Maven | 由 `labs/mvnw` 提供,无需本机预装 |

## 环境检查命令

```powershell
java -version
javac -version
echo $env:JAVA_HOME
cd labs && ./mvnw -v

依赖镜像 ​

项目内 labs/.mvn/settings.xml 已配置阿里云镜像,无需修改用户级 settings.xml。

常用命令 ​

powershell
cd labs
./mvnw -pl start compile          # 编译指定模块
./mvnw test                       # 全量测试
./mvnw -pl testing-unit test -Dtest=UserServiceTest   # 跑单个测试类

这份文档的实际价值:换电脑或重装系统时,照着它 10 分钟能恢复开发环境。

13. 掌握标准 ​

  • [ ] 能用 Markdown 写出结构清晰的文档;
  • [ ] 会用固定模板记录 Bug 与学习笔记;
  • [ ] 知道什么样的记录三个月后自己也看不懂;
  • [ ] 写出的内容包含可搜索的关键词(异常类名、方法名、命令)。

14. 扩展资源 ​

15. 下一步学习 ​

《如何向 AI 提问与审核 AI 代码》 会讲清 AI 协作的边界与审核方法——AI 生成的代码,最终要由你签字。

前置知识

无,可直接开始

后续知识

暂无

进度只保存在本机浏览器,可随时清除

个人学习项目:AI 生成内容均经人工复核,第三方资源仅作索引