夜间模式
写 JAVA 的好习惯
前言
好的开发习惯能帮助我们在日常开发工作中达到事半功倍的效果,增强代码的可读性、健壮性,减少代码漏洞,因此我们应当不懈的追求代码精进,培养好的开发习惯。
代码规范
- 写完代码,自测一下
- 方法入参尽量都校验
- 对于复杂的代码逻辑,添加清楚的注释
- 使用完
IO资源流,需要关闭 - 代码采取措施避免运行时错误(如数组边界溢出,被零除等)
- 尽量不在循环里远程调用、或者数据库操作,优先考虑批量进行
- 获取对象的属性,先判断对象是否为空
Set集合或者Map集合中的key为自定义对象时,要重写该对象的equals和hashCode方法- 避免使用双括号
的方式实例化对象,该写法虽然简洁但会生成匿名内部类,容易造成内存泄漏
js
new Person{{setName('xxx')}}- 不要在条件判断中写复杂的表达式
- 条件判断使用卫语句,增强代码可读性和健壮性
- 使用
equals()方法时,常量(有确定值)放前面 spring官方推荐使用构造器注入- 尽量不在循环中使用
try-catch,应把其放在最外层 - 常量声明为
static final,并以大写命名 - 不要创建一些不使用的对象,不要导入一些不使用的类
- 不要对超出范围的基本数据类型做向下强制转型
代码优化
- 尽量指定类、方法、变量的
final修饰符 - 尽量重用对象
- 尽可能使用局部变量
- 尽量减少对变量的重复计算
- 尽量采用懒加载的策略
- 如果能预估到数组、集合的内容长度,应在创建时指定长度
- 复制大量数据时,使用
System.arraycopy() - 乘法和除法使用移位操作
- 数组优先于列表
- 尽量在合适的场合使用单例
- 尽量避免使用静态变量
- 尽量避免使用反射
- 尽量使用
池化技术(数据库连接池、线程池) - 使用带缓冲的输入输出流进行
IO操作 public方法不要有太多的形参- 使用最有效率的方式去遍历
Map(推荐使用entrySet()遍历)
接口规约
- 接口需要考虑幂等性
- 接口入参需要做校验,推荐使用
@valid或者@validated校验框架 - 接口出参不允许为枚举值或任何包含枚举值的
pojo对象 - 修改老接口的时候,考虑接口的兼容性
- 调用第三方接口,需要考虑异常处理,安全性,超时重试这几个点
并发编程
- 多线程情况下,考虑线性安全问题
- 写完代码,脑洞一下多线程执行会怎样,注意并发一致性问题
- 多线程异步优先考虑恰当的线程池,而不是
new thread,同时考虑线程池是否隔离 - 使用
ThreadPoolExecutor构造器创建线程池,避免使用 Executors 的 静态方法创建线程池 - 使用
synchronized时尽量同步代码块 - 使用锁时尽量缩小锁定范围
缓存(redis)
- 使用缓存的时候,考虑缓存跟
DB的一致性 - 考虑缓存穿透、缓存雪崩、缓存击穿、缓存热点问题
- 避免使用
redis事务功能 - 禁止线上使用
keys、flushall、flushdb等,通过redis的rename机制禁掉命令,或者使用 scan 的方式渐进式处理 - 使用批量操作的命令提升效率
- 拒绝
big key(拆分key,使用合适的数据类型) - 控制
key的生命周期(分散设置过期时间) key名设计要有可读性、可管理性、简洁性,不要包含特殊字符- 设置合适的内存淘汰策略
数据库
- 手动写完代码业务的
SQL,先拿去数据库跑一下,同时也explain看下执行计划 - 数据库主从延迟问题考虑(必要时强制读主库)
- 避免在循环内做数据库的操作
SQL 规范
- 设计表的时候,所有表和字段都添加相应的注释
SQL书写格式,关键字大小保持一致,使用缩进INSERT语句标明对应的字段名称- 设计数据库表的时候,加上以下个字段(字段名可自定义):主键,
create*time,update_time,delete_flag - 尽量把所有列定义为
NOT NULL并提供默认值 - 所有表必须使用
Innodb存储引擎 - 数据库和表的字符集尽量统一使用
utf8/utf8mb4 - 如果修改字段含义或对字段表示的状态追加时,需要及时更新字段注释
- 索引命名要规范,主键索引名为
pk*字段名;唯一索引名为uk*字段名;普通索引为idx_字段名 - 禁止使用外键,如果有外键完整性约束,由应用程序控制
索引规范
- 避免在更新比较频繁、区分度不高的列上单独建立索引
- 需要
JOIN的字段,数据类型必须绝对一致; 多表关联查询时,保证被关联的字段需要有索引 - 建立联合索引时,必须将区分度更高的字段放在左边
- 在一个联合索引中,若第一列索引区分度等于 1,那么则不需要建立联合索引
- 利用覆盖索引来进行查询操作,避免回表
SQL 性能优化
- 写完
SQL先explain查看执行计划 - 写完
SQL语句,检查where,order by,group by后面的列,多表关联的列是否已加索引,优先考虑联合索引where后面的字段,留意其数据类型的隐式转换 - 尽量使用
varchar代替char,如果存储的字符串长度几乎相等,则使用char定长字符串类型 - 减少不必要的字段返回,如使用
select <具体字段> 代替 select * - where 从句中不对列进行函数转换和表达式计算
- 如果修改/更新数据过多,考虑批量进行
- 在一些场景下,考虑使用
timestamp代替datetime - 不使用%开头的模糊查询
- 尽量避免在
WHERE子句中使用or作为连接条件 JOIN的表不允许超过五个(一般不允许超过三个)- 不分页的集合查询应规定查询数量的上限,避免全量查询导致
OOM
SQL 后悔药
- 操作
delete或者update语句,加个limit - 变更
SQL操作先在测试环境执行,写明详细的操作步骤以及回滚方案,并在上生产前review - 修改或删除重要数据前,要先备份,先备份,先备份
- 修改或者删除
SQL,先写WHERE查一下,确认后再补充delete或update SQL命令行修改数据,养成begin + commit事务的习惯