作者丨silianpan
来源:https://juejin.im/post/5ada99fff265da0b8a672fbd
基于阿里巴巴JAVA开发规范整理
一、命名风格
【强制】类名使用 UpperCamelCase 风格,必须遵从驼峰形式,但以下情形例外:DO / BO / DTO / VO / AO
【强制】方法名、参数名、成员变量、局部变量都统一使用 lowerCamelCase 风格,必须遵从 驼峰形式。
【强制】常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。
【强制】抽象类命名使用 Abstract 或 Base 开头;异常类命名使用 Exception 结尾;测试类命名以它要测试的类的名称开始,以 Test 结尾。
【强制】Model 类中布尔类型的变量,都不要加 is,否则部分框架解析会引起序列化错误。
【强制】对于 Service 和 DAO 类,基于 SOA 的理念,暴露出来的服务一定是接口,内部的实现类用 Impl 的后缀与接口区别。正例:CacheManagerImpl 实现 CacheManager 接口。
【推荐】为了达到代码自解释的目标,任何自定义编程元素在命名时,使用尽量完整的单词组合来表达其意。
正例:从远程仓库拉取代码的类命名为PullCodeFromRemoteRepository
【推荐】接口类中的方法和属性不要加任何修饰符号(public 也不要加),保持代码的简洁 性,并加上有效 的Javadoc 注释。尽量不要在接口里定义变量,如果一定要定义变量,肯定是 与接口方法相关,并且是整个应用的基础常量。
【参考】枚举类名建议带上 Enum 后缀,枚举成员名称需要全大写,单词间用下划线隔开。
【参考】各层命名规约:
Service/DAO 层方法命名规约
二、变量定义
【推荐】不要使用一个常量类维护所有常量,按常量功能进行归类,分开维护。说明:大而全的常量类,非得使用查找功能才能定位到修改的常量,不利于理解和维护。
三、代码格式
【强制】大括号的使用约定。如果是大括号内为空,则简洁地写成{}即可,不需要换行;如果 是非空代码块则:
【强制】 左小括号和字符之间不出现空格;同样,右小括号和字符之间也不出现空格。
【强制】if/for/while/switch/do 等保留字与括号之间都必须加空格。
【强制】任何二目、三目运算符的左右两边都需要加一个空格。
【强制】采用 4 个空格缩进,禁止使用 tab 字符。
【强制】注释的双斜线与注释内容之间有且仅有一个空格。
正例:// 注释内容,注意在//和注释内容之间有一个空格。
【强制】方法参数在定义和传入时,多个参数逗号后边必须加空格。
【强制】IDE 的 text file encoding 设置为 UTF-8; IDE 中文件的换行符使用 Unix 格式,不要使用 Windows 格式。
【推荐】方法体内的执行语句组、变量的定义语句组、不同的业务逻辑之间或者不同的语义之间插入一个空行。相同业务逻辑和语义之间不需要插入空行。
四、OOP规约
【强制】所有的覆写方法,必须加@Override 注解。
【强制】不能使用过时的类或方法。
【强制】Object 的 equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals。
【强制】所有的相同类型的包装类对象之间值的比较,全部使用 equals 方法比较。
【强制】RPC 方法的返回值和参数必须使用包装数据类型。
【强制】构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在 init 方法中。
【推荐】当一个类有多个构造方法,或者多个同名方法,这些方法应该按顺序放置在一起, 便于阅读。
【推荐】循环体内,字符串的连接方式,使用 StringBuilder 的 append 方法进行扩展。
String str = "start";
for (int i = 0; i < 100; i++) {
str = str + "hello";
}
【推荐】慎用 Object 的 clone 方法来拷贝对象。说明:对象的 clone 方法默认是浅拷贝,若想实现深拷贝需要重写 clone 方法实现属性对象 的拷贝。
五、集合处理
【强制】使用集合转数组的方法,必须使用集合的 toArray(T[] array),传入的是类型完全一样的数组,大小就是 list.size()。
Listlist = new ArrayList (2);
list.add("guan");
list.add("bao");
String[] array = new String[list.size()];
array = list.toArray(array);
【强制】不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator方式,如果并发操作,需要对 Iterator 对象加锁。
【推荐】使用 entrySet 遍历 Map 类集合 KV,而不是 keySet 方式进行遍历。
六、控制语句
【强制】在一个 switch 块内,每个 case 要么通过 break/return 等来终止,要么注释说明程序将继续执行到哪一个 case 为止;在一个 switch 块内,都必须包含一个 default 语句并且 放在最后,即使它什么代码也没有。
【强制】在 if/else/for/while/do 语句中必须使用大括号。即使只有一行代码,避 单行的编码方式:if (condition) statements;
【推荐】除常用方法(如 getXxx/isXxx)等外,不要在条件判断中执行其它复杂的语句,将复 杂逻辑判断的结果赋值给一个有意义的布尔变量名,以提高可读性。
//伪代码如下
final boolean existed = (file.open(fileName, "w") != null) && (...) || (...);
if (existed) {
...
}
if ((file.open(fileName, "w") != null) && (...) || (...)) {
...
}
【推荐】循环体中的语句要考量性能,以下操作尽量移至循环体外处理,如定义对象、变量、 获取数据库连接,进行不必要的 try-catch 操作(这个 try-catch 是否可以移至循环体外)。
【参考】下列情形,需要进行参数校验:
七、注释规约
【强制】类、类属性、类方法的注释必须使用 Javadoc 规范,使用/*内容/ 格式,不得使用 // xxx 方式。
【强制】所有的抽象方法(包括接口中的方法)必须要用 Javadoc 注释、除了返回值、参数、 异常说明外,还必须指出该方法做什么事情,实现什么功能。
【强制】所有的类都必须添加创建者和创建日期。
【强制】方法内部单行注释,在被注释语句上方另起一行,使用//注释。方法内部多行注释 使用/* */注释,注意与代码对齐。
【强制】所有的枚举类型字段必须要有注释,说明每个数据项的用途。
【推荐】代码修改的同时,注释也要进行相应的修改,尤其是参数、返回值、异常、核心逻辑 等的修改。
【参考】谨慎注释掉代码。在上方详细说明,而不是简单地注释掉。如果无用,则删除。
【参考】对于注释的要求:第一、能够准确反应设计思想和代码逻辑;第二、能够描述业务含 义,使别的程序员能够迅速了解到代码背后的信息。完全没有注释的大段代码对于阅读者形同 天书,注释是给自己看的,即使隔很长时间,也能清晰理解当时的思路;注释也是给继任者看 的,使其能够快速接替自己的工作。
【参考】好的命名、代码结构是自解释的,注释力求精简准确、表达到位。避免出现注释的 一个极端:过多过滥的注释,代码的逻辑一旦修改,修改注释是相当大的负担。
【参考】特殊注释标记,请注明标记人与标记时间。注意及时处理这些标记,通过标记扫描, 经常清理此类标记。线上故障有时候就是来源于这些标记处的代码。
八、其他
【强制】在使用正则表达式时,利用好其预编译功能,可以有效加快正则匹配速度。说明:不要在方法体内定义:Pattern pattern = Pattern.compile(规则);
【强制】注意 Math.random() 这个方法返回是 double 类型,注意取值的范围 0≤x<1(能够 取到零值,注意除零异常),如果想获取整数类型的随机数,不要将 x 放大 10 的若干倍然后 取整,直接使用 Random 对象的 nextInt 或者 nextLong 方法。
【强制】获取当前毫秒数 System.currentTimeMillis(); 而不是 new Date().getTime();
【推荐】任何数据结构的构造或初始化,都应指定大小,避免数据结构无限增长吃光内存。
九、异常处理
【强制】捕获异常是为了处理它,不要捕获了却什么都不处理而抛弃之,如果不想处理它,请 将该异常抛给它的调用者。最外层的业务使用者,必须处理异常,将其转化为用户可以理解的 内容。
十、MySQL数据库
建立表规约
【强制】表名、字段名必须使用小写字母或数字,禁止出现数字开头,禁止两个下划线中间只 出现数字。数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑。
【强制】禁用保留字,如 desc、range、match、delayed 等,请参考 MySQL 官方保留字。
【强制】主键索引名为 pk_字段名;唯一索引名为 uk_字段名;普通索引名则为 idx_字段名。说明:pk_ 即 primary key;uk_ 即 unique key;idx_ 即 index 的简称。
【强制】小数类型为 decimal,禁止使用 float 和 double。
【强制】如果存储的字符串长度几乎相等,使用 char 定长字符串类型。
【强制】varchar 是可变长字符串,不预先分配存储空间,长度不要超过 5000,如果存储长度大于此值,定义字段类型为 text。
【强制】表必备三个字段:id,create_time, update_time, delete_flag
【强制】对于Boolean型的字段,采用decimal类型
【强制】表和字段都需要添加注释信息。
【推荐】单表行数超过 500 万行或者单表容量超过 2GB,才推荐进行分库分表。说明:如果预计三年后的数据量根本达不到这个级别,请不要在创建表时就分库分表。
【参考】合适的字符存储长度,不但节约数据库表空间、节约索引存储,更重要的是提升检 索速度。
索引规约
【强制】业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引。
【强制】超过三个表禁止 join。需要 join 的字段,数据类型必须绝对一致;多表关联查询时, 保证被关联的字段需要有索引。
【强制】在 varchar 字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据 实际文本区分度决定索引长度即可。
【参考】创建索引时避免有如下极端误解:
SQL语句
【强制】不要使用 count(列名)或 count(常量)来替代 count(),count()是 SQL92 定义的标准统计行数的语法,跟数据库无关,跟 NULL 和非 NULL 无关。
【强制】count(distinct col) 计算该列除 NULL 之外的不重复行数,注意 count(di col1, col2) 如果其中一列全为 NULL,那么即使另一列有不同的值,也返回为 0。
【强制】当某一列的值全是 NULL 时,count(col)的返回结果为 0,但 sum(col)的返回结果为NULL.
【强制】不得使用外键与级联,一切外键概念必须在应用层解决。
【强制】禁止使用存储过程,存储过程难以调试和扩展,更没有移植性。
【推荐】in 操作能避免则避免,若实在避免不了,需要仔细评估 in 后边的集合元素数量,控 制在 1000 个之内。
【参考】如果有全球化需要,所有的字符存储与表示,均以 utf-8 编码,注意字符 的区别。
【强制】更新数据表记录时,必须同时更新记录对应的 update_time 字段值为当前时间。
【参考】@Transactional 事务不要滥用。事务会影响数据库的 QPS,另外使用事务的地方需 要考虑各方面的回滚方案,包括缓存回滚、搜索引擎回滚、消息补偿、统计修正等。