Skip to main content

Java项目代码规范

作者:程序员马丁

在线博客:https://nageoffer.com

note

热门项目实战社群,收获国内众多知名公司面试青睐,近千名同学面试成功!助力你在校招或社招上拿个offer。

在实际开发过程中,不同程序员的编码风格千差万别。出于对代码整洁度的高度关注,我梳理并制定了一套适用于 Java 项目的编码规范,用以约束自身编码习惯,逐步形成清晰、统一、他人易于理解的代码风格。

该规范会持续迭代更新,以适应项目演进与团队协作的需求。

方法命名

1. 获取单个对象的方法用 get 或者 find 作前缀

例如:查询单个用户 getStudent,按照 ID 查询单个用户 getStudentById。

2. 获取多个对象的方法用 list 作前缀

例如:按照 IDS 查询多个用户,listStudentByIds。

3. 获取统计值的方法用 count 作前缀

例如:统计全量用户,countUser。

4. 插入的方法用 save 作前缀

例如:新增用户,saveUser。

5. 删除的方法用 remove 作前缀

例如:删除用户,removeUser。

6. 修改的方法用 update 作前缀

例如:修改用户,updateUser。

参数命名

1. 对象参数命名

许多同学在方法参数命名上较为随意,与其如此,不如制定统一的命名规范,以避免增加命名难度。针对 Controller、Service 和 Mapper 三层架构中的单个对象请求参数,建议统一使用 requestParam 进行命名。

示例如下:

/**
* 查询优惠券模板
*
* @param requestParam 请求参数
* @return 优惠券模板信息
*/
CouponTemplateQueryRespDTO findCouponTemplate(CouponTemplateQueryReqDTO requestParam);

2. 单参数命名

对于基础类型和引用类型,由于它们的语义较为单一,因此可以直接使用它们本身的语义单词进行命名。

/**
* 查询优惠券推送任务详情
*
* @param taskId 推送任务 ID
* @return 优惠券推送任务详情
*/
CouponTaskQueryRespDTO findCouponTaskById(String taskId);

领域模型命名规约

1. 数据对象

xxxDO,xxx 即为数据表名。比如学生数据对象:StudentDO。

2. 数据传输对象

xxxDTO,xxx 为业务领域相关的名称。

这里又分为两种,分别是请求入参和请求出参,以学生新增接口为例:

  • 入参:StudentSaveReqDTO
  • 出参:StudentSaveRespDTO

如果是分页查询学生接口,示例如下:

  • 入参:StudentPageQueryReqDTO
  • 出参:StudentPageQueryRespDTO

3. 项目配置类

xxxConfiguration,xxx 为配置类型。比如数据库持久层配置类:DataBaseConfiguration。

4. 常量类

xxxConstant,xxx 为常量领域。比如项目中公共 Redis 配置:RedisCommonConstant。

5. 上下文

xxxContext,xxx 为上下文类型。比如用户存储上下文:UserContext。

6. 枚举类

xxxEnum,xxx 表示什么类型的枚举。比如用户优惠券状态枚举:UserCouponStatusEnum。

7. 注意事项

POJO 是 DO/DTO/BO/VO 的统称,禁止命名成 xxxPOJO。

代码开发规约

【强制】类、方法和变量的命名要做到顾名思义,避免使用缩写。

【强制】静态变量使用大写,多个单词使用下划线连接。示例:MESSAGE_CENTER_SEND_TYPR。

【强制】捕获的异常名称命名为 ex ;捕获异常且不做任何事情,异常名称命名为 ignored。

【强制】返回值变量使用 result 命名;循环中使用 each 命名循环变量;map 中使用 entry 代替 each。

result 命名示范:
private void parseDate(String data) {
Result result = JSONUtil.parseObject(data, Result.class);
return result;
}
或采用 result 为前缀:
private void parseDate(String data) {
Result resultDate = JSONUtil.parseObject(data, Result.class);
return resultDate;
}

each 命名示范:
appNameLeaseMap.values().forEach(each -> appNameLeaseList.add(each));
或是 for 循环:
for (Lease<InstanceInfo> each : appNameLeaseMap.values()) {
appNameLeaseList.add(each);
}

【强制】业务系统中优先使用 Guava、HuTool、Common3 等工具类中的方法,不存在指定方法时再创建自定义工具类,禁止创建相同语义方法的工具类。

备注:定义组件项目时,尽量使用自定义工具类,避免因版本问题导致不确定的异常。

注释规范

1. 注释说明意图即可,无需补充冗余字段

【强制】Class、Interface、Enum、@interface 等文件类型,类上注释仅需说明类的意图即可。不需要补充时间和创建人,因为 往往开发代码的不止是一个人,容易造成信息干扰。需要的话,查看提交记录即可。

/**
* 适配第三方框架的线程池
*/
public interface ThreadPoolAdapter {

}

2. 方法上需要添加注释

【强制】方法上需添加注释,并说明清楚方法的意图(接口实现类无需注释);必要时描述 @param @return。

/**
* 适配第三方框架的线程池
*/
public interface ThreadPoolAdapter {

/**
* 修改框架线程池的核心参数
*
* @param threadPoolBaseInfo 修改线程池的基础参数
* @return 线程池核心参数修改结果
*/
boolean updateThreadPool(ThreadPoolBaseInfo threadPoolBaseInfo);
}

如果方法为内部引用方法,并且方法名称见名知意,无需方法注释。

3. 方法块内部注释规范

【强制】方法内部的注释,应该新起一行,而不是跟在代码后面。

正例:
// 刷新动态线程池参数
refreshDynamicPool(parameter, executor);

反例:
refreshDynamicPool(parameter, executor); // 刷新动态线程池参数

4. 方法命名说明方法本身意图

【强制】私有方法尽量通过方法命名说明方法语义。