学习的动力不止于此:


最近阅读了刘典武大神推荐的阿里巴巴Java开发手册泰山版。里面的很多规范不仅仅适用于Java。非常值得我们一起学习。

于是,我找了最新的版本–黄山版

正所谓,五岳归来不看山,黄山归来不看岳。最新版本——黄山下载地址在文章末尾。

它是以Java开发者为中心视角,划分为编程规约、异常日志、单元测试、安全规约、MySQL 数据库、工程结构、设计规约七个维度。

我就整理一些我目前用到的,推荐各位同学好好阅读,必有收获。

一、编程规约

  1. 所有编程相关的命名不能以下划线或美元符号开始或结尾。反例:_name / name_ / $first /first$

  2. 严禁使用中英文混合的方式,不能直接使用中文的方式,杜绝完全不规范的英文缩写

  3. 代码和注释中避免使用种族歧视性或侮辱性词语,例如blacklist/whitelist。改为blocklist/allowlist

  4. 类名使用大驼峰例如ForceCode ,方法名/参数名/成员变量/局部变量统一使用小驼峰例如:localValue

  5. 常量名全部大写,单词用下划线分割。不要嫌弃名字长。

  6. 抽象类命名使用Abstract或者Base开头,异常类用Exception结尾,测试类以Test结尾

  7. 类型与中括号紧挨相连来定义数组如String args[]

  8. 避免在子父类的成员变量之间或不同代码块的局部变量间采用完全相同的命名。

  9. 在常量与变量命名时,表示类型的名词放词尾,以提升辨识度。如 nameList,TERMINATED_THREAD_COUNT

  10. 接口类中的方法和属性不要加任何修饰符号,public也不要加,保持代码的简洁性,并加上相应的注释。

  11. 枚举类名带上Enum后缀,枚举成员名称需全部大写,单词间用下划线隔开。

  12. 获取单个对象的方法用get做前缀,多个则用list做前缀,复数结尾,如listObjects

  13. 获取统计值方法用count做前缀,插入的方法用save/insert做前缀

  14. 删除的方法用remove/delete做前缀,修改方法用update做前缀

  15. 不允许用魔法值(即未定义的常量)如if (1= =education){…} 这里的1不知道代表什么意思?替换成
    static final Integer UNIVERSITY_EDUCATION = 1;if (UNIVERSITY_EDUCATION==education){...}

  16. long或Long赋值时,数值后使用大写L,不能为小写l,小写容易跟数值1混淆。

  17. 浮点数类型后缀统一为大写的D或F

  18. 不要使用一个常量类维护所有常量,要按常量功能进行归类,分开维护。
    有五层:跨应用共享常量、应用内共享常量、子工程内共享常量、包内共享常量、类内共享常量。

  19. 如果大括号内为空,简洁地写成{}即可。若不为空则左大括号前不换行,后换行,右大括号前换行,若有else则不换行。若终止必换行

  20. 左小括号和右相连字符不需空格,右小括号与左字符不需空格。左大前需加空格。

  21. if/for/while/switch/do 保留字与左右括号间必须加空格

  22. 任何二目、三目的左右两边需加一个空格。采用4个空格缩进,禁止tab字符。如使用 Tab 缩进,必须设置 1 个 Tab 为 4 个空格。

  23. 注释的双斜线与注释内容间有且仅有一个空格,在进行类型强制转换时,右括号与强制转换值间不需任何空格隔开。

  24. 单行字符数限制不超过120个,超出需换行,第二行相对第一行缩进4个空格,从第三行开始不再继续缩进,运算符与下文一起换行,方法调用的点符合一起换行,方法调用中多个参数时在逗号后进行,在括号前不要换行。

  25. 方法在定义与传入时,多个参数逗号后必须加空格。 IDE中的文件编码为UTF-8,换行符用Unix,不要使用windows格式

  26. 避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成本,直接用类名访问即可。

  27. 所有的覆写方法,必须加@Override 注解。

  28. 相同的参数类型,相同的业务含义,才可以使用可变参数(尽量不用可变参数编程),参数类型避免定义为Object。

  29. 任何货币金额,均以最小货币单位且为整型类型进行存储。浮点数之间的等值判断,基本数据类型不能使用 == 进行比较,包装数据类型不能使用 equals进行判断。浮点数采用“尾数+阶码”的编码方式,类似于科学计数法的“有效数字+指数”的表示方式。二进制无法精确表示大部分的十进制小数。

  30. 指定一个误差范围,两个浮点数的差值在此范围之内,则认为是相等的。或者使用BigDecimal 来定义值,再进行浮点数的运算操作。BigDecimal 的等值比较应使用 compareTo() 方法,而不是 equals() 方法。equals() 方法会比较值和精度(1.0 与 1.00 返回结果为 false),而 compareTo() 则会忽略精度。

  31. 构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在 init 方法中。当一个类有多个构造方法,或者多个同名方法,这些方法应该按顺序放置在一起类内方法定义的顺序依次是:公有方法或保护方法 > 私有方法 > getter / setter 方法。说明:公有方法是类的调用者和维护者最关心的方法,首屏展示最好;保护方法虽然只是子类关心,也可能是“模板设计模式”下的核心方法;而私有方法外部一般不需要特别关心,是一个黑盒实现;因为承载的信息价值较低,所有Service 和 DAO 的 getter / setter 方法放在类体最后。

  32. final 可以声明类、成员变量、方法、以及本地变量,下列情况使用 final 关键字:
    1)不允许被继承的类,如:String 类。
    2)不允许修改引用的域对象,如:POJO 类的域变量。
    3)不允许被覆写的方法,如:POJO 类的 setter 方法。
    4)不允许运行过程中重新赋值的局部变量。
    5)避免上下文重复使用一个变量,使用 final 关键字可以强制重新定义一个变量,方便更好地进行重构。

  33. 禁止在程序中写死一年为 365 天,避免在公历闰年时出现日期转换错误或程序逻辑错误。
    避免公历闰年 2 月问题。闰年的 2 月份有 29 天,一年后的那一天不可能是 2 月 29 日。

  34. 判断所有集合内部的元素是否为空,使用 isEmpty() 方法(时间复杂度更低可读写好),而不是 size() == 0 的方式。高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁;能锁区块,就不要锁整个方法体;能用对象锁,就不要用类锁。对多个资源、数据库表、对象同时加锁时,需要保持一致的加锁顺序,否则可能会造成死锁。在使用阻塞等待获取锁的方式中,必须在 try 代码块之外,并且在加锁方法与 try 代码块之间没有任何可能抛出异常的方法调用,避免加锁成功后,在 finally 中无法解锁。

  35. 在使用尝试机制来获取锁的方式中,进入业务代码块之前,必须先判断当前线程是否持有锁。锁的释放规则与锁的阻塞等待方式相同。并发修改同一记录时,避免更新丢失,需要加锁。要么在应用层加锁,要么在缓存加锁,要么在数据库层使用乐观锁,使用 version 作为更新依据。

  36. 在一个 switch 块内,每个 case 要么通过 continue / break / return 等来终止,要么注释说明
    程序将继续执行到哪一个 case 为止;在一个 switch 块内,都必须包含一个 default 语句并且放在最后,即使它什么代码也没有。在 if / else / for / while / do 语句中必须使用大括号。

  37. 三目运算符 condition ” />下载地址

    阿里巴巴开发手册-华泰嵩黄山 – 副本.pdf