Java 静态检查与格式化
区分格式化、源码检查、编译器检查与字节码分析,并把相应规则接入构建反馈。
#concept
#growing
#dev
#java
[!info] related notes
Java 静态检查与格式化
这个概念为什么出现
测试抓行为;静态分析抓“看起来就能错”的模式:空指针风险、资源未关、错误相等性。格式化消灭风格战争。
[!abstract] 一句话理解 格式化器统一外观;静态分析/编译器插件在 CI 拦截高风险模式;它们补位测试,而不是替代测试。
最小可观察示例
场景:CI 中的质量门禁命令示意
# 需先在 POM 中配置并固定相应插件版本;SpotBugs 需要已编译字节码
mvn compile spotbugs:check
mvn -q checkstyle:check
# Gradle 需已应用 Spotless 插件并配置格式化规则
./gradlew spotlessCheck test
这些不是 Java 插件默认提供的全部任务;是否报错取决于插件、规则和失败阈值。直接运行插件目标也不能假设所有生命周期阶段都会自动执行。
错误示例模式(人工):
// 静态分析常警告:比较用了 == 对 Integer
Integer a = 128, b = 128;
if (a == b) { /* 比较对象身份,不能作为数值相等判断 */ }
结合场景再看三个关注点
- 本地检查缩短反馈,CI 强制运行相同规则以形成统一门禁。
- 抑制告警要写理由。
- 格式化自动化(save/pre-commit)。
核心概念与准确模型
1. 格式化
google-java-format 是格式化器;Spotless 编排格式化步骤及检查;EditorConfig 统一缩进、换行等编辑器设置,不独自完成 Java 语法格式化。
2. 静态分析家族
Checkstyle 主要检查源码风格,PMD 分析源码,Error Prone 接入 javac 编译,SpotBugs 分析编译后的字节码。Nullness 注解是否产生检查取决于配套分析器;仅加注解不等于编译器自动保证非空。
3. 类型强化
Optional、注解 nullness、不可变
边界情况与反直觉行为
- 误报需要基线治理。
- 规则过严导致“全 suppress”。
- 与 Lombok 等生成代码交互。
常见误区
[!warning] 常见误区:本地不跑、只靠审查 人脑不适合做格式警察与模式匹配。
工程实践
- 新项目第一天加 format+基础 bug 模式。
- 逐步打开错误级规则。
- 与 IDE 检查同步。
- 质量分阶段,不一次噎死。
本节总结
- 格式化统一噪声
- 静态分析降风险
- CI 强制执行
自测题
- 静态分析与单元测试如何分工?
- 为什么 suppress 要留注释?
参考答案
- 分析抓模式/通病;测试锁业务行为与回归。
- 防止无声绕过门禁,便于审计与后续清理。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| Error Prone | 工具 | 编译期检查 |
| SpotBugs | 工具 | 字节码分析 |