Java代码避坑指南
蝴蝶效应,系统崩溃可能就是程序员一个小不注意的点引起的。系统的维护过程,就是在漫长的系统运行过程中,将这些点一一扫除干净。本节课会学到很多这样的点,让我们提前避坑。
一、浮点数处理
1.1 货币类型选择
原则:任何货币金额,均以最小单位且整数类型进行存储。
比如:商品价格,以分为单位存储,一元的笔,价格存储为100整数。
1.2 浮点数问题根源
问题根源:精度丢失
根据浮点数的转换存储原理,了解精度丢失的原因。
1.3 避坑指南
1. 比较规则
基本数据类型,不能用 == 来比较;包装类型不能用equals来判断。
正确做法:指定误差范围,小于误差范围,则认为是相等的,例如:
float a = 1.0f - 0.9f;
float b = 0.9f - 0.8f;
float diff = 1e-6f;
if (Math.abs(a-b) < diff) {
System.out.println("true");
}
2. BigDecimal坑
BigDecimal应该使用compareTo()方法,而不是equals方法。
原理: equals方法既要比值,又要比精度。
BigDecimal构造时,使用String类型作为参数来构造,禁止使用浮点数。
二、日期时间类型
2.1 一气化三清:
传统DATE -> LocalDate, LocalTime, LocalDateTime, Instant
2.2 日期格式化坑
yyyy: 表示当天所在年份;
YYYY: 当天所在周所在的年份;
比如: 1999-12-27所在年份为1999,但是这一周被划归到2020年。
M和m: 月和分钟 H和h: 24小时制和12小时制。
2.3 获取当前毫秒数
建议使用
System.currentTimeMillis()
System.nanoTime()
java8建议使用Instant类
三、 控制语句避坑
3.1 控制语句之switch
- 每一个case都要用break来终止;否则注释一下执行到哪一个为止
- default必须包含,并放到最后
- 对String类型要判空,否则NPE
3.2 通用规则
必须使用大括号,即使只有一句代码
少用if-else方式,代码清晰。
3.3 三目 隐形坑
condition ? 表达式1 : 表达式2
原理:表达式1或表达式2只有有一个是原类型,就会强制拆箱成表示范围更大的那个类型。
NPE实例:
Integer a = 1;
Integer b = 2;
Integer c = null;
Boolean flag = false;
//a*b 的结果是int类型,那么c会强制拆箱成int类型,抛出NPE异常
Integer result = (flag ? a*b: c);
3.4 三不要
-
不要在其他表达式中插入复制语句
-
不要在条件判断中执行复杂语句,提高可读性
-
避免采用取反逻辑运算符
3.5 高并发场景,等值击穿
比如,判断库存不足时,应该使用
sku.getStock() <= 0
而不能使用
sku.getStock() == 0
3.6 参数校验
1. 需要校验的场景
2. 不需要校验的场景
四、OOP设计
分享一个面向对象编程的图片
4.1 面向对象四大特征
抽象:找出共同点
封装:高内聚
继承:复用
多态:扩展性
4.2 七大设计原则
4.3 OOP编程规约
1. 覆写方法Override
原理:让编译器去帮忙确认确实是覆写了,而不是一不小心搞个新的出来。
2. equals原则
-
所有整型包装类,都使用equals; 原理:虽然-127~128使用了缓存,==也可以,但是比较大的数据构造时,返回一个新对象。
-
使用常量或确定有值的对象来调用equals,避免NPE
3. 方法及属性
-
POJO类属性,必须使用包装类
-
定义DO,DTO,VO等,不要设定任何默认值
-
定义DO时,属性类型要和数据库字段类型匹配
-
getter/setter不要增加业务逻辑
-
禁止在POJO类中,同时对应属性的isXxx()和getXxx()
-
构造方法里面禁止加入任何业务逻辑,如果有放到init中
五、总结
学完汗流,感觉在日常已经犯了不少禁忌了。