Lmxy1990 ' Blog

Java 编程规范

编程规约


  1. 代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束。

  2. 常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚.

  3. POJO 类中布尔类型的变量,都不要加 is,否则部分框架解析会引起序列化错误。

  4. 接口类中的方法和属性不要加任何修饰符号(public 也不要加),保持代码的简洁.

  5. 不允许任何魔法值(即未经定义的常量)直接出现在代码中。

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

  7. 构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在 init 方法中。

  8. setter 方法中,参数名称与类成员变量名称一致,this.成员名 = 参数名。在 getter/setter 方法中,不要增加业务逻辑,增加排查问题的难度。

  9. 循环体内,字符串的连接方式,使用 StringBuilder 的 append 方法进行扩展。

  10. 对于Map,只要重写 equals,就必须重写 hashCode。

  11. 如果自定义对象做为 Map 的键,那么必须重写 hashCode 和 equals。

  12. ArrayList 的 subList 结果不可强转成 ArrayList,否则会抛出 ClassCastException 异常.

  13. 使用集合转数组的方法,必须使用集合的 toArray(T[] array),传入的是类型完全 一样的数组,大小就是 list.size()。

  14. 使用工具类 Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方 法,它的 add/remove/clear 方法会抛出 UnsupportedOperationException 异常。

  15. 泛型通配符<? extends T>来接收返回的数据,此写法的泛型集合不能使用 add 方 法,而<? super T>不能使用 get 方法,做为接口调用赋值时易出错。

  • 说明:扩展说一下 PECS(Producer Extends Consumer Super)原则:1)频繁往外读取内容 的,适合用上界 Extends。2)经常往里插入的,适合用下界 Super。
  1. 不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator方式,如果并发操作,需要对 Iterator 对象加锁。

  2. 集合初始化时,指定集合初始值大小。

  3. 使用 entrySet 遍历 Map 类集合 KV,而不是 keySet 方式进行遍历。

  4. 获取单例对象需要保证线程安全,其中的方法也要保证线程安全。

  5. SimpleDateFormat 是线程不安全的类,一般不要定义为 static 变量,如果定义为 static,必须加锁,或者使用 DateUtils 工具类。

  6. 高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁;能 锁区块,就不要锁整个方法体;能用对象锁,就不要用类锁。

  7. 并发修改同一记录时,避免更新丢失,需要加锁。要么在应用层加锁,要么在缓存加 锁,要么在数据库层使用乐观锁,使用 version 作为更新依据。 说明:如果每次访问冲突概率小于 20%,推荐使用乐观锁,否则使用悲观锁。乐观锁的重试次 数不得小于 3 次。

  8. 子线程抛出异常堆栈,不能在主线程 try-catch 到。

  9. 避免 Random 实例被多线程使用,虽然共享该实例是线程安全的,但会因竞争同一
    seed 导致的性能下降。

  10. volatile 解决多线程内存不可见问题。对于一写多读,是可以解决变量同步问题, 但是如果多写,同样无法解决线程安全问题。

  11. HashMap 在容量不够进行 resize 时由于高并发可能出现死链,导致 CPU 飙升,在
    开发过程中可以使用其它数据结构或加锁来规避此风险。

  12. 表达异常的分支时,少用 if-else 方式,这种方式可以改写成:if return ;

  13. 在使用正则表达式时,利用好其预编译功能,可以有效加快正则匹配速度。不要在方法体内定义:Pattern pattern = Pattern.compile(规则);

  14. 后台输送给页面的变量必须加$!{var}.如果 var=null 或者不存在,那么${var}会直接显示在页面上。

29.注意 Math.random() 这个方法返回是 double 类型,注意取值的范围 0≤x<1(能够 取到零值,注意除零异常),如果想获取整数类型的随机数,不要将 x 放大 10 的若干倍然后 取整,直接使用 Random 对象的 nextInt 或者 nextLong 方法。

  1. 获取当前毫秒数 System.currentTimeMillis(); 而不是 new Date().getTime();

  2. 异常不要用来做流程控制,条件控制,因为异常的处理效率比条件分支低。

  3. 捕获异常是为了处理它,不要捕获了却什么都不处理而抛弃之,如果不想处理它,请 将该异常抛给它的调用者。最外层的业务使用者,必须处理异常,将其转化为用户可以理解的 内容。

  4. 不能在 finally 块中使用 return,finally 块中的 return 返回后方法结束执行,不会再执行 try 块中的 return 语句。

  5. 应用中不可直接使用日志系统(Log4j、Logback)中的 API,而应依赖使用日志框架
    SLF4J 中的 API,使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一。

  6. 异常信息应该包括两类信息:案发现场信息和异常堆栈信息。如果不处理,那么通过 关键字 throws 往上抛出。

数据库


  1. 任何字段如果为非负数,必须是 unsigned。

  2. 表名、字段名必须使用小写字母或数字,禁止出现数字开头,禁止两个下划线中间只 出现数字。数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑。

  3. 表名不使用复数名词。

  4. 禁用保留字,如 desc、range、match、delayed 等,请参考 MySQL 官方保留字。

  5. 主键索引名为 pk字段名;唯一索引名为 uk字段名;普通索引名则为 idx_字段名。

  6. 小数类型为 decimal,禁止使用 float 和 double。

  7. varchar 是可变长字符串,不预先分配存储空间,长度不要超过 5000,如果存储长 度大于此值,定义字段类型为text,独立出来一张表,用主键来对应,避免影响其它字段索 引效率。

  8. 表的命名最好是加上“业务名称_表的作用”。

  9. 业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引。

  10. 超过三个表禁止 join。需要 join 的字段,数据类型必须绝对一致;多表关联查询 时,保证被关联的字段需要有索引。

  11. 页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决。

  12. 如果有 order by 的场景,请注意利用索引的有序性。order by 最后的字段是组合 索引的一部分,并且放在索引组合顺序的最后,避免出现 file_sort的情况,影响查询性能。

  13. 建组合索引的时候,区分度最高的在最左边。

  14. 防止因字段类型不同造成的隐式转换,导致索引失效。

  15. 不要使用 count(列名)或 count(常量)来替代 count(),count()是 SQL92 定义的 标准统计行数的语法,跟数据库无关,跟 NULL 和非 NULL 无关。

  16. count(distinct col) 计算该列除 NULL 之外的不重复行数,注意 count(distinct col1, col2) 如果其中一列全为 NULL,那么即使另一列有不同的值,也返回为 0。

  17. 当某一列的值全是 NULL 时,count(col)的返回结果为 0,但 sum(col)的返回结果为 NULL,因此使用 sum()时需注意 NPE 问题。

  18. 禁止使用存储过程,存储过程难以调试和扩展,更没有移植性。

  19. in 操作能避免则避免,若实在避免不了,需要仔细评估 in 后边的集合元素数量,控 制在 1000 个之内。

  20. POJO 类的布尔属性不能加 is,而数据库字段必须加 is_,要求在 resultMap 中进行 字段与属性之间的映射。

  21. sql.xml 配置参数使用:#{},#param# 不要使用${} 此种方式容易出现 SQL 注入。

  22. @Transactional 事务不要滥用。事务会影响数据库的 QPS,另外使用事务的地方需 要考虑各方面的回滚方案,包括缓存回滚、搜索引擎回滚、消息补偿、统计修正等。


End

坚持原创技术分享,您的支持将鼓励我继续创作!