(一)命名风格
1-1、【必须】代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束。
反例:__name 、$Object 、name_、name$
1-2、【必须】代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式
(正确的英文拼写和语法可以让阅读者易理解,避免歧义)
1-3、【必须】类名使用 UpperCamelCase 风格,必须遵从大写驼峰形式
正例:ManagerSave
1-4、【必须】方法名、参数名、成员变量、局部变量都统一使用 lowerCamelCase 风格,必须遵从 小写驼峰形式。
正例:localValue 、 getHttpMessage() 、inputUserId
1-5、【必须】常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。
正例:MAX_STOCK_COUNT
反例:MAX_COUNT
1-6、【必须】获取单个对象的方法用 get 做前缀。
1-7、【必须】获取多个对象的方法用 list 做前缀。
1-8、【必须】获取统计值的方法用 count 做前缀。
1-9、【必须】插入的方法用 save/insert 做前缀。
1-10、【必须】删除的方法用 remove/delete 做前缀。
1-11、【必须】修改的方法用 update 做前缀。
1-12、【必须】long 或者 Long 初始赋值时,使用大写的 L,不能是小写的 l,小写容易跟数字 1 混 淆,造成误解。
正例:Long a =2L;
反例:Long a = 2l;
(二)代码格式
2-1、【必须】大括号的使用约定。如果是大括号内为空,则简洁地写成{}即可,不需要换行;如果 是非空代码块则:
1) 左大括号前不换行。
2) 左大括号后换行。
3) 右大括号前换行。
4) 右大括号后还有 else 等代码则不换行;表示终止的右大括号后必须换行。
2-2、【必须】单行字符数限制不超过 120 个,超出需要换行,换行时遵循如下原则:第二行相对第一行缩进 4 个空格,从第三行开始,不再继续缩进,参考示例。
1) 运算符与下文一起换行。
2) 方法调用的点符号与下文一起换行。
3) 方法调用时,多个参数,需要换行时,在逗号后进行。
4) 在括号前不要换行,见反例。
2-3、【必须】2-1、2-2两条必须注意,其他空格如若嫌弃麻烦请在写完代码后再ieda中使用快捷键格式化代码 (alt+ctrl+L)
(三)代码约束
3-1、【必须】相同参数类型,相同业务含义,才可以使用 Java 的可变参数,避免使用 Object。(尽量不用可变参数编程)
正例:public User getUsers(String type, Integer age) {......}
反例:public User getUsers(String type, Object age) {......}
3-2、【必须】不能使用过时的类或方法。
3-3、【必须】Object 的 equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals。
正例:"test".equals(object);
反例:object.equals("test");
3-4、当一个类有多个构造方法,或者多个同名方法,这些方法应该按顺序放置在一起, 便于阅读。
3-5、【必须】在 getter/setter 方法中,不要增加业务逻辑,增加排查问题的难度。
3-6、【必须】使用集合转数组的方法,必须使用集合的 toArray(T[] array),传入的是类型完全 一样的数组,大小就是 list.size()。
正例:
List list = new ArrayList(2);
list.add("guan"); list.add("bao");
String[] array = new String[list.size()];
array = list.toArray(array);
3-7、【必须】集合初始化时,指定集合初始值大小。如果暂时无法确定初始值大小,请设置为 16(即默认值)
正例:
HashMap 使用 HashMap(int initialCapacity) 初始化,
Map<String, Object> liurl = new HashMap<>(16);
3-8、避免采用取反逻辑运算符。取反逻辑不利于快速理解,并且取反逻辑写法必然存在对应的正向逻辑写法。
正例:if (x < 628)
反例:if (!(x >= 628))
3-9、如果是JDK8,尽量使用 Map.foreach 方法来遍历集合。
3-10、【必须】请注意 Map 类集合 K/V 能不能存储 null 值的情况
集合类 | Key | Value | Super | 说明 |
Hashtable | 不允许为 null | 不允许为 null | Dictionary | 线程安全 |
ConcurrentHashMap | 不允许为 null | 不允许为 null | AbstractMap | 锁分段技术(JDK8:CAS) |
TreeMap | 不允许为 null | 允许为 null | AbstractMap | 线程不安全 |
HashMap | 允许为 null | 允许为 null | AbstractMap | 线程不安全 |
3-11、【必须】在一个 switch 块内,每个 case 要么通过 break/return 等来终止,要么注释说明程 序将继续执行到哪一个 case 为止;在一个 switch 块内,都必须包含一个 default 语句并且 放在最后,即使它什么代码也没有。
3-12、【必须】在 if/else/for/while/do 语句中必须使用大括号。即使只有一行代码,避免采用 单行的编码方式:if (condition) statements;
3-13、不要在条件判断中执行其它复杂的语句,将复 杂逻辑判断的结果赋值给一个有意义的布尔变量名,以提高可读性。
正例: final boolean existed = (file.open(fileName, "w") != null) && (...) || (...);
if (existed) { ... }
反例: if ((file.open(fileName, "w") != null) && (...) || (...)) { ... }
3-14、【必须】异常不要用来做流程控制,条件控制,因为异常的处理效率比条件分支低。
3-15、【必须】禁止对大段代码进行 try-catch。catch 时请分清稳定代码和非稳定代码,稳定代码指的是无论如何不会出错的代码。对于非稳定代码的 catch 尽可能进行区分异常类型,再做对应的异常处理。
3-16、【必须】捕获异常是为了处理它,不要捕获了却什么都不处理而抛弃之,如果不想处理它,请 将该异常抛给它的调用者。最外层的业务使用者,必须处理异常,将其转化为用户可以理解的 内容。
3-17、【必须】有 try 块放到了事务代码中,catch 异常后,如果需要回滚事务,一定要注意手动回 滚事务。
3-18、【必须】捕获异常与抛异常,必须是完全匹配,或者捕获异常是抛异常的父类。
(四)注释约束
4-1、【必须】类、类属性、类方法的注释必须使用 Javadoc 规范,使用/**内容*/格式,不得使用 // xxx 方式。
正例:
/**
* 获取用户信息
* @param userId 用户id
*/
反例:// 获取用户信息
(idea 中输入 /** 回车,可以快捷生成注释)
4-2、【必须】所有的类都必须添加创建者和创建日期。 idea中如何添加创建者和日期请参考练几个:https://jingyan.baidu.com/article/154b463136fc1728ca8f41bf.html
4-3、【必须】方法内部单行注释,在被注释语句上方另起一行,使用//注释。方法内部多行注释 使用/* */注释,注意与代码对齐。
4-4、【必须】所有的枚举类型字段必须要有注释,说明每个数据项的用途。
4-5、【必须】代码修改的同时,注释也要进行相应的修改,尤其是参数、返回值、异常、核心逻辑 等的修改。
4-6、【必须】谨慎注释掉代码。在上方详细说明,而不是简单地注释掉。如果无用,则删除。
(五)数据库约束
5-1、【必须】表达是与否概念的字段,必须使用 is_xxx 的方式命名
正例:表达逻辑删除的字段名 is_deleted,1 表示删除,0 表示未删除。
5-2、【必须】表名、字段名必须使用小写字母或数字,禁止出现数字开头,禁止两个下划线中间只 出现数字。数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑。
5-3、【必须】禁用保留字,如 desc、range、match、delayed 等,请参考所用数据库类型官方保留字。
5-4、小数类型为 decimal,禁止使用 float 和 double。如存储数据范围超过decimal范围,建议将数据拆成整数和小数分开存储。
5-5、【必须】大字段需要独立出来一张表,用主键来对应,避免影响其它字段索 引效率。
5-6、【必须】业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引。
5-7、【必须】超过三个表禁止 join。需要 join 的字段,数据类型必须绝对一致;多表关联查询时,被关联的字段最好有索引。
(六)SQL约束
6-1、【必须】不要使用 count(列名)或 count(常量)来替代 count(*),count(*)是 SQL92 定义的 标准统计行数的语法,跟数据库无关,跟NULL和非 NULL 无关。count(*)会统计值为 NULL 的行,而 count(列名)不会统计此列为 NULL 值的行
6-2、【必须】使用 ISNULL()来判断是否为 NULL 值。
6-3、【必须】数据订正时,删除和修改记录时,要先 select,避免出现误删除,确认无误才能执 行更新语句。
6-4、【必须】in 操作能避免则避免,若实在避免不了,需要仔细评估 in 后边的集合元素数量,控 制在 1000 个之内。
6-5、【必须】不要使用“select * from ……”返回所有列,只检索需要的列,可避免后续因表结构变化导致的不必要的程序修改,还可降低额外 消耗的资源
正例:select cust_name from CustInfo where cust_no = ‘10000050’。
反例:select * from CustInfo where cust_no = ‘10000050’。
6-7、【必须】不要检索已知的列。
正例:select cust_name from CustInfo where cust_no = ‘10000050’。
反例:select cust_no, cust_name from CustInfo where cust_no = ‘10000050’。
6-8、【必须】使用高选择性的where子句,让数据库返回必须的数据集,而不是返回大量数据给应用程序,再由应用程序进行筛选,返回大 数据集的代价很高。
6-9、尽量用相同数据类型进行比较,避免发生数据类型转换。
6-10、尽量使用可参数化的搜索条件,如=, >, >=, <, <=, between, in, is null以及like ‘<literal>%’
6-11、尽量不要使用非参数化的负向查询,这将导致无法使用索引,如<>, !=, !>, !<, not in, not like, not exists, not between, is not null, like ‘%<literal>’