name: java-coding-standards description: “适用于Spring Boot服务的Java编码规范:命名、不可变性、Optional使用、流、异常、泛型以及项目布局。”
Java 编码规范
适用于Spring Boot服务中可读、可维护的Java(17+)代码规范。
核心原则
- 清晰性优先于巧妙性
- 默认不可变;最小化共享可变状态
- 使用有意义的异常快速失败
- 一致的命名和包结构
命名
// ✅ 类/记录:PascalCase
public class MarketService {}
public record Money(BigDecimal amount, Currency currency) {}
// ✅ 方法/字段:camelCase
private final MarketRepository marketRepository;
public Market findBySlug(String slug) {}
// ✅ 常量:UPPER_SNAKE_CASE
private static final int MAX_PAGE_SIZE = 100;
不可变性
// ✅ 优先使用记录和final字段
public record MarketDto(Long id, String name, MarketStatus status) {}
public class Market {
private final Long id;
private final String name;
// 仅提供getter,不提供setter
}
Optional 使用
// ✅ 从find*方法返回Optional
Optional<Market> market = marketRepository.findBySlug(slug);
// ✅ 使用map/flatMap代替get()
return market
.map(MarketResponse::from)
.orElseThrow(() -> new EntityNotFoundException("市场未找到"));
流最佳实践
// ✅ 使用流进行转换,保持管道简短
List<String> names = markets.stream()
.map(Market::name)
.filter(Objects::nonNull)
.toList();
// ❌ 避免复杂的嵌套流;为了清晰性,优先使用循环
异常
- 对领域错误使用非受检异常;用上下文包装技术异常
- 创建领域特定的异常(例如
MarketNotFoundException) - 除非在中心位置重新抛出/记录日志,否则避免宽泛的
catch (Exception ex)
throw new MarketNotFoundException(slug);
泛型和类型安全
- 避免原始类型;声明泛型参数
- 对于可复用的工具类,优先使用有界泛型
public <T extends Identifiable> Map<Long, T> indexById(Collection<T> items) { ... }
项目结构(Maven/Gradle)
src/main/java/com/example/app/
config/
controller/
service/
repository/
domain/
dto/
util/
src/main/resources/
application.yml
src/test/java/... (镜像main结构)
格式化和风格
- 一致地使用2或4个空格(项目标准)
- 每个文件一个公共顶级类型
- 保持方法简短且专注;提取辅助方法
- 成员顺序:常量、字段、构造器、公共方法、受保护方法、私有方法
应避免的代码异味
- 长参数列表 → 使用DTO/构建器
- 深层嵌套 → 提前返回
- 魔法数字 → 命名常量
- 静态可变状态 → 优先使用依赖注入
- 静默捕获块 → 记录日志并处理或重新抛出
日志记录
private static final Logger log = LoggerFactory.getLogger(MarketService.class);
log.info("fetch_market slug={}", slug);
log.error("failed_fetch_market slug={}", slug, ex);
空值处理
- 仅在不可避免时接受
@Nullable;否则使用@NonNull - 在输入上使用Bean验证(
@NotNull、@NotBlank)
测试期望
- JUnit 5 + AssertJ 用于流畅断言
- Mockito 用于模拟;尽可能避免部分模拟
- 优先使用确定性测试;没有隐藏的睡眠
记住:保持代码意图明确、类型安全且可观察。除非证明有必要,否则优先考虑可维护性而非微优化。