一、命名风格
1)类名使用UpperCamelCase风格
正例:UserService
2)方法名、参数名、成员变量、局部变量都统一使用lowerCamelCase风格
正例:userId getUserById()
3)常量命名全部大写,单词间用下划线隔开
正例:MAX_NUMBER
4)抽象类命名使用Abstract开头;异常类命名使用Exception结尾;测试类命名以它要测试的类名称开始,以Test结尾。
5)在常量与变量的命名时,表示类型的名词放在词尾,以提升辨识度。
正例:startTime workQueue userList
6)枚举类名带上Enum后缀,枚举成员名称需要全大写,单词间用下划线隔开。
说明:枚举其实是特殊的常量类,且构造方法被默认强制是私有。
正例:枚举名称为DeviceTypeEnum的成员名称:LIGHT INVALID_DEVICE
7)如果模块、接口、类、方法使用了设计模式,在命名时需体现出具体模式。
说明:将设计模式体现在名字中,有利于阅读者快速理解架构设计理念。
正例:public class OrderFactory;
public class LoginProxy;
8)各层命名规约:
- Service/Mapper层方法命名规约
(1)获取单个对象的方法用get做前缀,如:getUserById()。
(2)获取多个对象的方法用list做前缀,复数结尾,如:listUsers()。
(3)获取统计值的方法用count做前缀,如:countUser()。
(4)插入的方法用save/insert做前缀,如:saveUser() or insertUser()。
(5)删除的方法用remove/delete做前缀,如:removeUser() or deleteUser()。
(6)修改的方法用update做前缀,如:updateUser()。
二、代码格式
1)IDE的text file encoding 设置为UTF-8;IDE中文件的换行符使用Unix格式,不要使用Windows格式。
2)大括号样式
- 左大括号前不换行。
- 左大括号后换行。
- 右大括号前换行。
- 右大括号后还有else等代码则不换行;表示终止的右大括号后必须换行。
if (a==b) {
// do something
} else {
// do something
}
3)if / for / while / switch / do 等保留字与括号之间都必须加空格。
4)单行字符数限制不超过120个,超出换行,换行时遵循如下原则:
- 第二行相对第一行缩进4个空格,第三行开始,不在继续缩进。
- 运算符和下文一起换行。
- 方法调用的点符号与下文一起换行。
- 方法调用的多个参数需要换行时,在逗号后进行。
- 在括号前不要换行。
StringBuilder sb = new StringBuilder();
sb.append("张三").append("李四")
.append("王五") ;
5)单个方法的总行数不超过 80 行。
三、控制语句
1)在高并发场景中,避免使用“等于”判断作为中断或退出条件。
说明:如果并发控制没有处理好,容易产生等值判断被击穿的情况,使用大于或小于的区间判断条件来代替。
2)表达异常的分支时,少用if-else方式,这种方式可以改写成:
if (condition) {
....
retrun obj;
}
说明:如果使用 if()...else if()...else... 方式表达逻辑,避免后续代码维护困难,请勿操作4层。
四、集合处理
1)判断集合内部元素是否为空,使用isEmpty()方法,而不是size()=0。
2)使用Map的方法keySet() / values() / entrySet() 返回集合对象时,不可以对其进行添加操作,否则会抛出UnsupportedOperationException异常。
3)使用集合转数组的方法,必须使用集合的toArray(T[] array),传入的是类型完全一致、长度为0的空数组。
4)不要在foreach循环里进行元素的remove / add操作。remove元素请使用Iterator方式,如果并发操作,需要对Iterator对象加锁。
List<String> list = new ArrayList<>();
list.add("1");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
if (删除元素的条件) {
iterator.remove();
}
}
五、OOP规约
1)Object的equals方法容易抛空指针异常,应使用常量或确定有值的对象来调用equals。
正例:"test".equals(object);
反例:object.equals("test");
2)所有整型包装类对象之间值的比较,全部使用equals方法比较。
说明:对于 Integer var = ? 在 -128 至 127 之间的赋值,Integer 对象是在 IntegerCache.cache 产生,会复用已有对象,这个区间内的 Integer 值可以使用 == 进行判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是一个大坑,推荐使用 equals 方法进行判断。
3)基本数据类型与包装数据类型的使用标准
(1)局部变量使用基本数据类型
(2)数据实体类属性使用包装数据类型
(3)RPC方法的返回值和参数使用包装数据类型
4)当一个类有多个同名方法,这些方法应该按顺序放置在一起,便于阅读。
5)类内方法定义的顺序:getter/setter方法 > 公有方法或保护方法 > 私有方法。
6)循环体中,字符串的连接方式,使用 StringBuilder 的 append 方法进行扩展。
7)构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在 init 方法中。
五、前后端交互规约
1)前后端交互的API,需要明确协议、域名、路径、请求方法、请求内容、状态码、响应体。
六、MySQL 数据库
(一)建表规约
1)表名、字段名必须使用小写字母或数字。
正例:username password
2)表名不使用复数名词。
3)禁用保留字,如desc、range、match、delayed等,请参考MySQL官方保留字。
4)索引:主键索引名为pk_字段名;唯一索引名为uk_字段名;普通索引名则为idx_字段名。
说明:pk_ 即 primary key; uk_ 即 unique key; idx_ 即 index的简称。
5)varchar 是可变长字符串, 不预先分配存储空间,长度不要超过5000,如果存储长度大于此值,定义字段类型为text,定义一张表,用主键来对应,避免影响其它字段索引效率。