Leave the campground cleaner than you found it. (要让离开时的营地比进入时更加干净。)
作为一名程序员,对代码格式要有一些基本的要求,比如命名规范,空格等。
良好的代码规范不仅能让项目看起来干净,还能够减少低级错误,提高代码质量。
目前普遍认同阿里巴巴提供的代码规范阿里巴巴Java开发手册
在团队中口头要求可能达不到约束的作用,checkstyle配合IDEA插件可以在编译器做静态代码检查。
1. 配置
首先安装IDEA插件CheckStyle-IDEA
:
重启IDEA后,底部工具拦会出现CheckStyle窗口,点开可以看到相关功能:
- 切换检查模版文件
- 对当前文件进行检查
- 对当前module进行检查
- 对当前项目进行检查
其中插件自带两个模板文件,一个是Sun公司提供的,一个是Google提供的,这两个检查相对严格,不建议直接使用。
这里我们自己添加一个模版文件,只做必要的检查:
新建一个文件,命名可以任意,然后在插件配置中,添加该模板文件即可:
2. 常见的代码规范
2.1 命名风格
- 代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束。
- 类名使用
UpperCamelCase
风格。 - 方法名、参数名、成员变量、局部变量都统一使用
lowerCamelCase
风格,必须遵从 驼峰形式。 - 常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。
- POJO 类中布尔类型的变量,都不要加
is
前缀,否则部分框架解析会引起序列化错误。
反例:定义为基本数据类型Boolean isDeleted的属性,它的方法也是isDeleted(),RPC框架在反向解析的时候,“误以为”对应的属性名称是 deleted,导致属性获取不到,进而抛出异常。 - 包名尽量使用小写,但有时会出现多个单词组合的情况,那么也使用
lowerCamelCase
风格即可。包名统一使用单数形式,但是类名如果有复数含义,类名可以使用复数形式。 - 接口类中的方法和属性不要加任何修饰符号(public也不要加),保持代码的简洁性,并加上有效的
Javadoc
注释。尽量不要在接口里定义变量,如果一定要定义变量,肯定是与接口方法相关,并且是整个应用的基础常量。 - 【参考】Service/DAO层方法命名规约:
- 获取单个对象的方法用get做前缀。
- 获取多个对象的方法用list做前缀,复数形式结尾如:listObjects。
- 获取统计值的方法用count做前缀。
- 插入的方法用save/insert做前缀。
- 删除的方法用remove/delete做前缀。
- 修改的方法用update做前缀。
2.2 常量定义
- 不允许任何魔法值(即未经预先定义的常量)直接出现在代码中。
- 在 long 或者 Long 赋值时,数值后使用大写的 L,不能是小写的 l,小写容易跟数字 1 混淆,造成误解。
- 不要使用一个常量类维护所有常量,要按常量功能进行归类,分开维护。
- 如果变量值仅在一个固定范围内变化用 enum 类型来定义。
2.3 代码格式
基本的格式示例
123456789101112131415161718public static void main(String[] args) {// 缩进 4 个空格. 注释的双斜线与注释内容之间有且仅有一个空格。String say = "hello";// 运算符的左右必须有一个空格int flag = 0;// 关键词 if 与括号之间必须有一个空格,括号内的 f 与左括号,0 与右括号不需要空格if (flag == 0) {System.out.println(say);}// 左大括号前加空格且不换行;左大括号后换行if (flag == 1) {System.out.println("world");// 右大括号前换行,右大括号后有 else,不用换行} else {System.out.println("ok");// 在右大括号后直接结束,则必须换行}}单行字符数限制不超过 120 个,超出需要换行
123456StringBuffer sb = new StringBuffer();// 超过 120 个字符的情况下,换行缩进 4 个空格,点号和方法名称一起换行sb.append("zi").append("xin")....append("huang")....append("huang")....append("huang");方法参数在定义和传入时,多个参数逗号后边必须加空格。
- 【推荐】单个方法的总行数不超过 80 行。
- 【推荐】不同逻辑、不同语义、不同业务的代码之间插入一个空行分隔开来以提升可读性。
2.4 OOP 规约
- 所有的覆写方法,必须加@Override 注解。
- Object 的 equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals。如
"test".equals(object);
- 所有的相同类型的包装类对象之间值的比较,全部使用
equals
方法比较。对于Integer var = ?
在-128 至 127 范围内的赋值,Integer 对象是在 IntegerCache.cache 产生,会复用已有对象,这个区间内的 Integer 值可以直接使用==进行 判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是一个大坑, 推荐使用 equals 方法进行判断。 - 关于基本数据类型与包装数据类型的使用标准如下:
- 【强制】所有的POJO类属性必须使用包装数据类型。POJO 类属性没有初值是提醒使用者在需要使用时,必须自己显式地进行赋值,任何NPE 问题,或者入库检查,都由使用者来保证。数据库的查询结果可能是 null,因为自动拆箱,用基本数据类型接收有 NPE 风险。
- 【强制】RPC方法的返回值和参数必须使用包装数据类型。
- 【推荐】所有的局部变量使用基本数据类型。
- 定义 DO/DTO/VO 等 POJO 类时,不要设定任何属性默认值。POJO 类的 createTime 默认值为 new Date(),但是这个属性在数据提取时并没有置入具体值,在更新其它字段时又附带更新了此字段,导致创建时间被修改成当前时间。
- POJO 类必须写 toString 方法。使用 IDE 中的工具:source> generate toString 时,如果继承了另一个 POJO 类,注意在前面加一下 super.toString。不要使用JSON工具类实现,因为json序列化有性能消耗。
2.5 日志
调试时使用的日志,上线前必须删除。
关键逻辑必须记录日志,并包含相关参数信息。写下这条日志时,要清楚其作用,怎么定位,能用来挽救谁的性命。
日志需要控制级别,大量地输出无效日志,不利于系统性能提升,也不利于快速定位错误点。
统一使用slf4j日志框架,不要使用加号拼接参数,而是使用占位符。