一、编程规约 (一)命名风格
命名不能以下划线开头
尽量使用英文进行命名,禁止使用拼音与英文结合,尽量减少纯拼音的命名
类的命名为大驼峰命名法,即首字母大写以及后面每个词的首字母都大写
方法名、参数名、成员变量、局部变量统一使用小驼峰命名法,即首字母小写以及后面每个词的首字母都大写
常量命名全部大写,单词用下划线隔开,需明确表达出意思,命名可以很长
异常类使用Exception结尾,抽象类使用Abstract或Base开头,测试类以Test结尾
定义数组时,将中括号与类型紧挨相连,如:String[] array
定义普通bean时,布尔值的成员变量不要加is前缀,反例:isDeleted
包名统一使用小写,例:com.cmbhz.controller
命名是避免忘文不生意的情况
如果使用了设计模式,则在命名中体现出来有利于理解,例如:OrderFactory
枚举类名建议带上Enum后缀,实现类用Impl后缀
数据对象命名:xxxDO
数据传输对象:xxxDTO
展示对象:xxxVO
(二)常量定义
不允许未经定义的常量直接出现在代码中,例如String key = “stgood” + myId;
Long类型初始化时,请使用大写的L
不同作用的常量类请分类定义,例如:RedisConsts,CacheConsts
(三)代码格式
如果大括号内为空,不要换行,写成{}
如果大括号非空,则应当按下方格式输入
1 2 3 if (a == b) { //a和b与括号之间没有空格,if等保留字与括号之间有空格,运算符左右保留空格 //TODO } //如果还有 else 等代码则不换行;表示终止的右大括号后必须换行
缩进代码时必须为4个空格,而非tab,如需使用tab键进行缩进,IDEA与Eclipse需进行相关设置
注释符与注释内容之间需保留一个空格
单行字符如果超过120个,则需要进行换行,规则如下:
1 2 3 4 5 6 7 StringBuffer sb = new StringBuffer(); sb.append("cmb").append("hz")..... .append("cmb").append("hz").... //第二行及以后相对于第一行缩进4个空格,运算符一起换行 .append("good"); //括号前不允许换行 method(arg1, arg2, arg3,..., //方法调用如果需要换行,在逗号后面换行 argX);
方法参数在定义与传入时,多个参数逗号后需要保留一个空格,例如:method(a, b, c)
IDE 的 text file encoding 设置为 UTF-8; IDE 中文件的换行符使用 Unix 格式,不要使用 Windows 格式
不同逻辑、不同语义、不同业务的代码之间插入一个空行分隔开来以提升可读性,但不需要多个空格隔开
(四)OOP规约
避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成本,直接用类名来访问即可
所有的重写都要加@Override注解
外部正在调用或者二方库依赖的接口,不允许修改方法签名,避免对接口调用方产生影响。接口过时必须加@Deprecated 注解,并清晰地说明采用的新接口或者新服务是什么
不能使用过时的类或方法
使用”test”.equals(Object),而不是Object.equals(“test”)
所有的相同类型的包装类对象之间值的比较,全部使用 equals 方法比较
关于基本数据类型与包装数据类型的使用标准如下:
所有的 POJO 类属性必须使用包装数据类型
RPC 方法的返回值和参数必须使用包装数据类型
序列化类新增属性时,请不要修改 serialVersionUID 字段,避免反序列失败;如果完全不兼容升级,避免反序列化混乱,那么请修改 serialVersionUID 值
构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在 init 方法中
类内方法定义的顺序依次是:公有方法或保护方法 > 私有方法 > getter/setter方法
getter与setter方法中不要增加业务逻辑
循环体内,字符串的连接方式,使用 StringBuilder 的 append 方法进行扩展
工具类不允许有 public 或 default 构造方法
(五)集合处理
关于 hashCode 和 equals 的处理,遵循如下规则:
只要重写 equals,就必须重写 hashCode
因为 Set 存储的是不重复的对象,依据 hashCode 和 equals 进行判断,所以 Set 存储的对象必须重写这两个方法
如果自定义对象作为 Map 的键,那么必须重写 hashCode 和 equals
不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator方式,如果并发操作,需要对 Iterator 对象加锁
1 2 3 4 5 6 7 Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { String item = iterator.next(); if (删除元素的条件) { iterator.remove(); } }
使用 entrySet 遍历 Map 类集合 KV,而不是 keySet 方式进行遍历,因为keySet遍历了2次,二entrySet之遍历了一次
高度注意 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
线程不安全
利用 Set 元素唯一的特性,可以快速对一个集合进行去重操作,避免使用 List 的 contains 方法进行遍历、对比、去重操作
(六)并发处理
线程资源必须通过线程池提供,不允许在应用中自行显式创建线程
高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁;能锁区块,就不要锁整个方法体;能用对象锁,就不要用类锁
对多个资源、数据库表、对象同时加锁时,需要保持一致的加锁顺序,否则可能会造成死锁
避免 Random 实例被多线程使用,虽然共享该实例是线程安全的,但会因竞争同一seed 导致的性能下降
(七)控制语句
在 if/else/for/while/do 语句中必须使用大括号,即使只有一行代码
在高并发场景中,避免使用”等于”判断作为中断或退出的条件
避免采用取反逻辑运算符,尽量采用正向逻辑,例如:if (x < 123)
(八)注释规约
类、类属性、类方法的注释必须使用 Javadoc 规范,使用/*内容 /格式
标签
描述
示例
@author
表示一个类的作者
@author description
@version
指定类的版本
@version info
@param
说明一个方法的参数
@param parameter-name explanation
@return
说明返回值类型
@return explanation
所有的类都必须添加创建者和创建日期
方法内部单行注释,在被注释语句上方另起一行,使用//注释
与其“半吊子”英文来注释,不如用中文注释把问题说清楚
所有的枚举类型字段必须要有注释,说明每个数据项的用途
谨慎注释掉代码。在上方详细说明,而不是简单地注释掉
(九)异常处理
catch 时请分清稳定代码和非稳定代码,稳定代码指的是无论如何不会出错的代码。对于非稳定代码的 catch 尽可能进行区分异常类型,再做对应的异常处理
捕获异常是为了处理它,不要捕获了却什么都不处理而抛弃之,如果不想处理它,请将该异常抛给它的调用者。最外层的业务使用者,必须处理异常,将其转化为用户可以理解的内容
finally 块必须对资源对象、流对象进行关闭,有异常也要做 try-catch
不要在 finally 块中使用 return,如果在finally中增加return则不会执行try中的return
方法的返回值可以为 null,不强制返回空集合,或者空对象等,必须添加注释充分说明什么情况下会返回 null 值
(十)日志规约
应用中不可直接使用日志系统(Log4j、Logback)中的 API,而应依赖使用日志框架SLF4J 中的 API,使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一
对 trace/debug/info 级别的日志输出,必须使用条件输出形式或者使用占位符的方式
1 2 3 4 5 6 7 8 9 10 正确: if (logger.isDebugEnabled()) { logger.debug("Processing trade with id: " + id + " and symbol: " + symbol); } 正确: logger.debug("Processing trade with id: {} and symbol : {} ", id, symbol); 错误(将日志设置成info时还是会占用资源): logger.debug("Processing trade with id: " + id + " and symbol: " + symbol);
避免重复打印日志,浪费磁盘空间,务必在 log4j.xml 中设置 additivity=false
异常信息应该包括两类信息:案发现场信息和异常堆栈信息。如果不处理,那么通过关键字 throws 往上抛出
生产环境禁止输出 debug 日志;有选择地输出 info 日志
error 级别只记录系统逻辑出错、异常或者重要的错误信息
(十一)安全规约
用户敏感数据禁止直接展示,必须对展示数据进行脱敏
用户请求传入的任何参数必须做有效性验证
(十二)其他
获取当前毫秒数 System.currentTimeMillis(); 而不是 new Date().getTime();
及时清理不再使用的代码段或配置信息
在使用平台资源,譬如短信、邮件、电话、下单、支付,必须实现正确的防重放限制,如数量限制、疲劳度控制、验证码校验,避免被滥刷导致资损
参考资料: 阿里巴巴Java开发手册
为正常使用来必力评论功能请激活JavaScript