前言:其实从阿里巴巴发布开发Java规范的第一版的时候就注意到了,每次更新也都会下载最新的,也随意的翻过几次,由于各种原因最终没有一次把规范完整的看完,主要是发现大部分就是自己的规范,自己平时就是按照这个规范来的。最近在调整历史项目,时间相对来说成块了很多,而且希望在调整的过程中有一个指导,就再一次拿起来规范,这一次一气呵成,终于把规范看完了,如下是我自己认为对自己有用的点,在个人以后的编程生涯中要注意。

  • 编程规范
  • 常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。
  • 中括号是数组类型的一部分,数组定义如下:String[] args。
  • POJO类中布尔类型的变量,都不要加is,否则部分框架解析会引起序列化错误。
  • 接口类中的方法和属性不要加任何修饰符号(public 也不要加),保持代码的简洁性,并加上有效的Javadoc注释。尽量不要在接口里定义变量,如果一定要定义变量,肯定是与接口方法相关,并且是整个应用的基础常量。
  • 不允许任何魔法值(即未经定义的常量)直接出现在代码中。
  • final可以声明类、成员变量、方法、以及本地变量,下列情况使用final关键字
  • 不允许被继承的类,如:String类。
  • 不允许修改引用的域对象,如:POJO类的域变量。
  • 不允许被重写的方法,如:POJO类的setter方法。
  • 不允许运行过程中重新赋值的局部变量。
  • 避免上下文重复使用一个变量,使用final描述可以强制重新定义一个变量,方便更好地进行重构。
  • 泛型通配符<? extends T>来接收返回的数据,此写法的泛型集合不能使用add方法,而<? super T>不能使用get方法,做为接口调用赋值时易出错。
  • 使用entrySet遍历Map类集合KV,而不是keySet方式进行遍历。keySet其实是遍历了2次,一次是转为Iterator对象,另一次是从hashMap中取出key所对应的value。而entrySet只是遍历了一次就把key和value都放到了entry中,效率更高。如果是JDK8,使用Map.foreach方法。
  • SimpleDateFormat 是线程不安全的类,一般不要定义为static变量,如果定义为static,必须加锁,或者使用DateUtils工具类。
  • 在一个switch块内,每个case要么通过break/return等来终止,要么注释说明程序将继续执行到哪一个case为止;在一个switch块内,都必须包含一个default语句并且放在最后,即使它什么代码也没有。
  • 循环体中的语句要考量性能,以下操作尽量移至循环体外处理,如定义对象、变量、获取数据库连接,进行不必要的try-catch操作(这个try-catch是否可以移至循环体外)
  • 异常日志
  • 对大段代码进行try-catch,这是不负责任的表现。catch时请分清稳定代码和非稳定代码,稳定代码指的是无论如何不会出错的代码。对于非稳定代码的catch尽可能进行区分异常类型,再做对应的异常处理。
  • 方法的返回值可以为null,不强制返回空集合,或者空对象等,必须添加注释充分说明什么情况下会返回null值。调用方需要进行null判断防止NPE问题。
  • 应用中不可直接使用日志系统(Log4j、Logback)中的API,而应依赖使用日志框架SLF4J中的API,使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一。
  • 对trace/debug/info级别的日志输出,必须使用条件输出形式或者使用占位符的方式。
  • 数据库
  • in操作能避免则避免,若实在避免不了,需要仔细评估in后边的集合元素数量,控制在1000个之内。
  • 小数类型为decimal,禁止使用float和double。
  • 单表行数超过500万行或者单表容量超过2GB,才推荐进行分库分表。
  • 利用延迟关联或者子查询优化超多分页场景。MySQL并不是跳过offset行,而是取offset+N行,然后返回放弃前offset行,返回N行,那当offset特别大的时候,效率就非常的低下,要么控制返回的总页数,要么对超过特定阈值的页数进行SQL改写。先快速定位需要获取的id段,然后再关联:SELECT a.* FROM 表1 a, (select id from 表1 where 条件 LIMIT 100000,20 ) b where a.id=b.id
  • 建组合索引的时候,区分度最高的在最左边。如果where a=? and b=? ,a列的几乎接近于唯一值,那么只需要单建idx_a索引即可。存在非等号和等号混合判断条件时,在建索引时,请把等号条件的列前置。如:where a>? and b=? 那么即使a的区分度更高,也必须把b放在索引的最前列。
  • 不要使用count(列名)或count(常量)来替代count(),count()是SQL92定义的标准统计行数的语法,跟数据库无关,跟NULL和非NULL无关。count(*)会统计值为NULL的行,而count(列名)不会统计此列为NULL值的行。