简洁清爽的代码风格是大多数工程师的追求。在工作中,作者就常常因为起名字而纠结,夸张点可以说是编程 5 分钟,命名 2 小时,所以今天我总结了一份 Java 开发者都需要的一份终极命名规范指南!!
每个公司都有不同的标准,目的是为了保持统一,减少沟通成本,提升团队研发效能。本文结合阿里巴巴开发规范及作者的工作经验,对 Java 领域的相关命名进行整理和总结,供大家参考。希望能为大家在命名时提供一些思路和指导。
文章目录
1、Java 中的命名规范
良好的命名规范是高质量代码的基石之一。在 Java 中,命名规范不仅帮助保持代码的整洁性和一致性,还能极大地提高代码的可读性和可维护性。遵循这样的规范,可以让其他开发者(包括未来的自己)更容易理解代码的功能和用途,从而更快地进行代码审查和修改。
Java 中常用到的命名形式共有三种,既 ①、首字母大写的 UpperCamelCase, ②、首字母小写的 lowerCamelCase 以及 ③、全部大写的并用下划线分割单词的 UPPERCAMELUNSER_SCORE。
通常约定,类一般采用大驼峰命名,方法和局部变量使用小驼峰命名,而大写下划线命名通常是常量和枚举中使用。
类型(名) | 约束 | 例子 |
---|---|---|
项目 | 全部小写,多个单词用中划线 “-” 分隔 | spring-cloud |
包 | 全部小写 | com.alibaba.fastjson |
类 | 单词首字母大写 | Feature 、FieldDeserializer |
变量 | 首字母小写的多词组合中,除首词外每词首字母大写 | userName 、password |
常量 | 全部大写,多个单词用下划线 “_” 分隔 | CACHE_EXPIRED_TIME |
方法 | 同变量 | read() 、getById(Long id) |
2、Java 中的包命名
在 Java 开发中,包名应全部使用小写字母,并以点 “.” 作为分隔符。包名通常由四部分组成:「前缀」、「发起者名」、「项目名」、「模块名」。
包名遵循单数形式,但如果类的命名有复数含义,则可以使用复数形式。
常见的前缀可以分为以下几种:
前缀 | 含义 | 例子 |
---|---|---|
indi | 个体项目个人发起,但非独自完成可公开或私有项目,Copyright(版权) 主要属于发起者。 | indi.发起者名.项目名.模块名.…… |
onem | 同 “indi”,标识个体项目个人发起,项目可能涉及多人合作,可公开或私有,Copyright 主要属于发起者。 | onem.发起者名.项目名.模块名.…… |
pers | 个人项目指个人发起,独自完成,可分享的项目,Copyright 主要属于个人 | pers.个人名.项目名.模块名.…… |
priv | 私有项目,指个人发起,独自完成非公开的私人使用的项目,Copyright 属于个人。 | priv.个人名.项目名.模块名.…… |
team | 团队项目,指由团队发起并由该团队开发的项目,Copyright 属于该团队所有 | team.团队名.项目名.模块名.…… |
顶级域名 | 公司项目 Copyright 由项目发起的公司所有,如 com(公司名)、org(非盈利组织名)、edu(教育机构) | com.公司名.项目名.模块名.…… |
3、Java 中的类命名
类名使用大驼峰命名形式,类命通常时名词或名词短语,接口名除了用名词和名词短语以外,还可以使用形容词或形容词短语,如 Cloneable
,Callable
等,表示实现该接口的类有某种功能或能力。对于测试类则以它要测试的类开头,以 Test
结尾,如 HashMapTest
。
对于一些特殊特有名词缩写也可以使用全大写命名,比如 XMLHttpRequest
,不过作者认为缩写三个字母以内都大写,超过三个字母则按照要给单词算。不过这个没有明确标准,比如阿里巴巴的 FastJson 就使用 JSONObject
作为类命,而 Google 则使用 JsonObjectRequest
命名,对于这种特殊的缩写,原则是统一就好。
属性(类) | 约束 | 例子 |
---|---|---|
抽象 | Abstract 或 Base 开头 | BaseUserService 、AbstractUserService |
枚举 | Enum 作为后缀 | ButtonTypeEnum |
工具 | Utils 作为后缀 | StringUtils |
异常 | Exception 结尾 | RuntimeException |
接口实现 | 接口名 + Impl | UserServiceImpl |
领域模型相 | DO、DTO、VO、DAO、Mapper | 正例:UserDAO 反例:UserDao |
设计模式相关 | Builder ,Factory 等 | 当使用到设计模式时要使用对应的设计模式作为后缀如 ThreadFactory |
处理特定功能 | Handler ,PredicateValidator | 表示处理器,校验器,断言这些类工厂还有配套的方法名如handle ,predicate ,validate |
测试 | 使用 Test 后缀 | UserServiceTest 表示用来测试 UserService 类的 |
MVC分层 | 使用 Controller ,Service ,ServiceImpl ,DAO 后缀 | UserManageController 、UserService 、UserServiceImpl``UserManageDAO |
4、Java 中的方法命名
方法命名采用小驼峰的形式,首字小写,往后的每个单词首字母都要大写。和类名不同的是,方法命名一般为动词或动词短语,与参数或参数名共同组成动宾短语,即「动词 + 名词」。一个好的函数名一般能通过名字直接获知该函数实现什么样的功能。
4.1、返回真伪值的方法
(单词)位置 | 单词 | 意义 | 例 |
---|---|---|---|
前缀 | is | 对象是否符合期待的状态 | isValid |
前缀 | can | 对象能否执行所期待的动作 | canRemove |
前缀 | should | 调用方执行某个命令或方法是好还是不好应不应该,或者说推荐还是不推荐 | shouldMigrate |
前缀 | has | 对象是否持有所期待的数据和属性 | hasObservers |
前缀 | needs | 调用方是否需要执行某个命令或方法 | needsMigrate |
4.2、用来检查的方法
(单词)位置 | 单词 | 意义 | 例 |
---|---|---|---|
前缀 | ensure | 确保对象处于期待的状态,不是则采取措施 | ensureCapacity |
前缀 | validate | 验证对象是否符合预期的正确状态,不是则采取措施 | validateInputs |
4.3、按需求才执行的方法
(单词)位置 | 单词 | 意义 | 例 |
---|---|---|---|
后缀 | IfNeeded | 需要的时候执行,不需要则什么都不做 | drawIfNeeded |
前缀 | might | 可能执行,视情况而定 | mightCreate |
前缀 | try | 尝试执行,失败时抛出异常或返回错误代码 | tryCreate |
后缀 | OrDefault | 尝试执行,失败时返回默认值 | getOrDefault |
后缀 | OrElse | 尝试执行,失败时返回指定的值 | getOrElse |
前缀 | force | 强制执行,失败抛出异常或返回错误代码 | forceCreate , forceStop |
4.4、异步相关方法
(单词)位置 | 单词 | 意义 | 例 |
---|---|---|---|
前缀 | blocking | 线程阻塞方法 | blockingGetUser |
后缀 | InBackground | 执行在后台线程 | doInBackground |
后缀 | Async | 异步方法 | sendAsync |
后缀 | Sync | 同步方法 | sendSync |
前缀/后缀 | schedule | Job和Task放入队列 | schedule , scheduleJob |
前缀/后缀 | post | 同上 | postJob |
前缀/后缀 | execute | 执行异步或同步方法 | execute , executeTask |
前缀/后缀 | start | 同上 | start , startJob |
前缀/后缀 | cancel | 停止异步方法 | cancel , cancelJob |
前缀/后缀 | stop | 同上 | stop , stopJob |
4.5、回调方法
(单词)位置 | 单词 | 意义 | 例 |
---|---|---|---|
前缀 | on | 事件发生时执行 | onCompleted |
前缀 | before | 事件发生前执行 | beforeUpdate |
前缀 | pre | 同上 | preUpdate |
前缀 | will | 同上 | willUpdate |
前缀 | after | 事件发生后执行 | afterUpdate |
前缀 | post | 同上 | postUpdate |
前缀 | did | 同上 | didUpdate |
前缀 | should | 确认事件是否可以执行 | shouldUpdate |
4.6、操作对象生命周期的方法
(单词)位置 | 单词 | 意义 | 例 |
---|---|---|---|
前缀 | initialize | 初始化或延迟初始化使用 | initialize |
前缀 | pause | 暂停 | onPause , pause |
前缀 | stop | 停止 | onStop , stop |
前缀 | abandon | 销毁的替代 | abandon |
前缀 | destroy | 同上 | destroy |
前缀 | dispose | 同上 | dispose |
4.7、与集合操作相关的方法
(单词)位置 | 单词 | 意义 | 例 |
---|---|---|---|
前缀 | contains | 是包含指定对象相同的对象 | contains |
前缀 | add | 添加 | addJob |
前缀 | append | 添加 | appendJob |
前缀 | insert | 插入到下标 n | insertJob |
前缀 | put | 添加与 key 对应的元素 | putJob |
前缀 | remove | 移除元素 | removeJob |
前缀 | enqueue | 添加到队列的最末位 | enqueueJob |
前缀 | dequeue | 从队列中头部取出并移除 | dequeueJob |
前缀 | push | 添加到栈头 | pushJob |
前缀 | pop | 从栈头取出并移除 | popJob |
前缀 | peek | 从栈头取出但不移除 | peekJob |
前缀 | find | 寻找符合条件的某物 | findById |
4.8、与数据相关的方法
(单词)位置 | 单词 | 意义 | 例 |
---|---|---|---|
前缀 | create | 新创建 | createAccount |
前缀 | new | 新创建 | newAccount |
前缀 | from | 从既有的某物新建或是从其他的数据新建 | fromConfig |
前缀 | to | 转换 | toString |
前缀 | update | 更新既有某物 | updateAccount |
前缀 | load | 读取 | loadAccount |
前缀 | fetch | 远程读取 | fetchAccount |
前缀 | delete | 删除 | deleteAccount |
前缀 | remove | 删除 | removeAccount |
前缀 | save | 保存 | saveAccount |
前缀 | store | 保存 | storeAccount |
前缀 | commit | 保存 | commitChange |
前缀 | apply | 保存或应用 | applyChange |
前缀 | clear | 清除或是恢复到初始状态 | clearAll |
前缀 | reset | 清除或是恢复到初始状态 | resetAll |
前缀 | find | 查找(单个) | findAccountById |
前缀 | query | 条件查询 | queryAccountsByStatus |
前缀 | list | 列表查询 | listAllAccounts |
前缀 | search | 搜索 | searchAccounts |
前缀 | retrieve | 检索 | retrieveAccountDetails |
前缀 | get | 获取(单个) | getAccountById |
4.9 成对出现的动词
动词 | 意义 | 动词 | 意义 |
---|---|---|---|
get | 获取 | set | 设置 |
add | 增加 | remove | 删除 |
create | 创建 | destroy | 销毁 |
start | 启动 | stop | 停止 |
open | 打开 | close | 关闭 |
read | 读取 | write | 写入 |
load | 载入 | save | 保存 |
begin | 开始 | end | 结束 |
backup | 备份 | restore | 恢复 |
import | 导入 | export | 导出 |
split | 分割 | merge | 合并 |
inject | 注入 | extract | 提取 |
attach | 附着 | detach | 脱离 |
bind | 绑定 | separate | 分离 |
view | 查看 | browse | 浏览 |
edit | 编辑 | modify | 修改 |
select | 选取 | mark | 标记 |
copy | 复制 | paste | 粘贴 |
undo | 撤销 | redo | 重做 |
insert | 插入 | delete | 删除 |
clean | 清理 | clear | 清除 |
index | 索引 | sort | 排序 |
find | 查找 | search | 搜索 |
increase | 增加 | decrease | 减少 |
play | 播放 | pause | 暂停 |
launch | 启动 | run | 运行 |
compile | 编译 | execute | 执行 |
debug | 调试 | trace | 跟踪 |
observe | 观察 | listen | 监听 |
build | 构建 | publish | 发布 |
input | 输入 | output | 输出 |
encode | 编码 | decode | 解码 |
encrypt | 加密 | decrypt | 解密 |
compress | 压缩 | decompress | 解压缩 |
pack | 打包 | unpack | 解包 |
parse | 解析 | emit | 生成 |
connect | 连接 | disconnect | 断开 |
send | 发送 | receive | 接收 |
download | 下载 | upload | 上传 |
refresh | 刷新 | synchronize | 同步 |
update | 更新 | revert | 复原 |
lock | 锁定 | unlock | 解锁 |
check out | 签出 | check in | 签入 |
submit | 提交 | commit | 交付 |
push | 推 | pull | 拉 |
expand | 展开 | collapse | 折叠 |
begin | 起始 | end | 结束 |
start | 开始 | finish | 完成 |
enter | 进入 | exit | 退出 |
abort | 放弃 | quit | 离开 |
obsolete | 废弃 | depreciate | 废旧 |
collect | 收集 | aggregate | 聚集 |
5、Java 中的变量&常量命名
5.1、变量命名
变量是指在程序运行中可以改变其值的量,包括成员变量和局部变量。变量名由多单词组成时,第一个单词的首字母小写,其后单词的首字母大写,俗称骆驼式命名法(也称驼峰命名法),如 computedValues
,index
、变量命名时,尽量简短且能清楚的表达变量的作用,命名体现具体的业务含义即可。
变量名不应以下划线或美元符号开头,尽管这在语法上是允许的。变量名应简短且富于描述。变量名的选用应该易于记忆,即,能够指出其用途。尽量避免单个字符的变量名,除非是一次性的临时变量。POJO 中的布尔变量,都不要加 is
(数据库中的布尔字段全都要加 is_
前缀)。
5.2、常量命名
常量命名 CONSTANT_CASE
,一般采用全部大写(作为方法参数时除外),单词间用下划线分割。那么什么是常量呢?
常量是在作用域内保持不变的值,一般使用 final
进行修饰。一般分为三种,全局常量(public static final
修饰),类内常量(private static final
修饰)以及局部常量(方法内,或者参数中的常量),局部常量比较特殊,通常采用小驼峰命名即可。
例子:
/**
* 一个demo
*
* @author lizhengi
* @date 2024-06-04 00:20
**/
public class HelloWorld {
//局部常量(正例)
public static final long USER_MESSAGE_CACHE_EXPIRE_TIME = 3600;
//局部常量(反例,命名不清晰)
public static final long MESSAGE_CACHE_TIME = 3600;
// 全局常量
private static final String ERROR_MESSAGE = "error message";
//成员变量
private int currentUserId;
/**
* 控制台打印 {@code message} 信息
*
* @param message 消息体,局部常量
*/
public void sayHello ( final String message ) {
System.out.println("Hello world!");
}
}
在命名常量时,清晰的命名比简洁更重要,尤其是这些常量在代码中扮演重要的配置或参数角色。清晰的命名有助于理解常量的具体用途,减少错误,并使得代码的维护和阅读更为直观。
以"用户消息缓存过期时间"为例,这是一个涉及时间参数的常量,可能在多个地方使用。以下是两种可能的命名方式,:
USER_MSG_CACHE_EXPIRY_TIME
UMCT_EXPIRATION
我们可以评估哪种更为清晰,一目了然
5.3、通用命名规则
-
尽量不要使用拼音;杜绝拼音和英文混用。对于一些通用的表示或者难以用英文描述的可以采用拼音,一旦采用拼音就坚决不能和英文混用。正例:
BeiJing
,HangZhou
反例:validateCanShu
; -
命名过程中尽量不要出现特殊的字符,常量除外;
-
尽量不要和 JDK 或者框架中已存在的类重名,也不能使用 Java 中的关键字命名。
-
妙用介词,如
for
(可以用同音的 4 代替),to
(可用同音的 2 代替),from
,with
,of
等。如类名采用User4RedisDO
,方法名getUserInfoFromRedis
,convertJson2Map
等。
6、Java 中的代码注解
6.1、注解的原则
好的命名增加代码阅读性,代码的命名往往有严格的限制。而注解不同,程序员往往可以自由发挥,单并不意味着可以为所欲为之胡作非为。优雅的注解通常要满足三要素。
-
“Nothing is strange”:没有注解的代码对于阅读者非常不友好,哪怕代码写的在清除,阅读者至少从心理上会有抵触,更何况代码中往往有许多复杂的逻辑,所以一定要写注解,不仅要记录代码的逻辑,还有说清楚修改的逻辑;
-
“Less is more”:从代码维护角度来讲,代码中的注解一定是精华中的精华。合理清晰的命名能让代码易于理解,对于逻辑简单且命名规范,能够清楚表达代码功能的代码不需要注解。滥用注解会增加额外的负担,更何况大部分都是废话(
// 根据id获取信息【废话注解】
); -
“Advance with the time”:注解应该随着代码的变动而改变,注解表达的信息要与代码中完全一致。通常情况下修改代码后一定要修改注解。
6.2、注解格式
注解大体上可以分为两种,一种是 JavaDoc 注解,另一种是简单注解。JavaDoc 注解可以生成 JavaAP I为外部用户提供有效的支持 JavaDoc 注解通常在使用 IDEA,或者 Eclipse 等开发工具时都可以自动生成,也支持自定义的注解模板,仅需要对对应的字段进行解释。参与同一项目开发的同学,尽量设置成相同的注解模板。
6.2.1、包注解
包注解在工作中往往比较特殊,通过包注解可以快速知悉当前包下代码是用来实现哪些功能,强烈建议工作中加上,尤其是对于一些比较复杂的包,包注解一般在包的根目录下,名称统一为 package-info.java
。
/**
* 落地也质量检测
* 1. 用来解决什么问题
* 对广告主投放的广告落地页进行性能检测,模拟不同的系统,如Android,IOS等; 模拟不同的网络:2G,3G,4G,wifi等
* 2. 如何实现
* 基于chrome浏览器,用chromedriver驱动浏览器,设置对应的网络,OS参数,获取到浏览器返回结果。
* 注意:网络环境配置信息{@link cn.mycookies.landingpagecheck.meta.NetWorkSpeedEnum}目前使用是常规速度,可以根据实际情况进行调整
* @author lizhengi
* @time 2024-06-04 00:20
*/
package cn.maruifu.landingpagecheck;
6.2.2、类注接
JavaDoc 注解中,每个类都必须有注解。
/**
* Copyright (C), 2019-2020, XiaoMage balabala...
* 类的介绍:这是一个用来做什么事情的类,有哪些功能,用到的技术.....
* @author 类创建者姓名 保持对齐
* @date 创建日期 保持对齐
* @version 版本号 保持对齐
*/
6.2.3、属性注解
在每个属性前面必须加上属性注释,通常有一下两种形式,至于怎么选择,你高兴就好,不过一个项目中要保持统一。
/** 提示信息 */
private String userName;
/**
* 密码
*/
private String password;
6.2.4、方法注释
在每个方法前面必须加上方法注释,对于方法中的每个参数,以及返回值都要有说明。
/**
* 方法的详细说明,能干嘛,怎么实现的,注意事项...
* @param xxx 参数1的使用说明, 能否为 null
* @return 返回结果的说明, 不同情况下会返回怎样的结果
* @throws 异常类型 注明从此类方法中抛出异常的说明
*/
6.2.5、构造方法注释
在每个构造方法前面必须加上注释,注释模板如下:
/**
* 构造方法的详细说明
* @param xxx 参数1的使用说明, 能否为 null
* @throws 异常类型 注明从此类方法中抛出异常的说明
*/
而简单注解往往是需要工程师字节定义,在使用注解时应该注意一下几点:
- 枚举类的各个属性值都要使用注解,枚举可以理解为是常量,通常不会发生改变,通常会被在多个地方引用,对枚举的修改和添加属性通常会带来很大的影响。
- 保持排版整洁,不要使用行尾注释;双斜杠和星号之后要用 1 个空格分隔。
例子:
int id = 1 ; // 反例:不要使用行尾注释
//反例:换行符与注释之间没有缩进
int age = 18 ;
// 正例:姓名
String name ;
/**
* 1. 多行注释
*
* 2. 对于不同的逻辑说明,可以用空行分隔
*/