易混淆点记录:
1.所有 整形包装类对象 之间,全部使用equals方法比较。
说明:对于Integer var = ?在-128 至127 范围内的赋值,Integer对象是在 IntegerCache.cache 产生,会复用已有对象,这个区间内的Integer值可以直接用==进行判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是一个大坑。推荐使用equals方法进行判断。
2.浮点数之间的等值判断,基本数据类型用 == 来比较,包装数据类型用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");
}
BigDecimal a = new BigDecimal("1.0");
BigDecimal b = new BigDecimal("0.9");
BigDecimal c = new BigDecimal("0.8");
BigDecimal x = a.subtract(b);
BigDecimal y = b.subtract(c);
if (x.equals(y)) {
System.out.println("true");
}
3.为了防止精度缺失,禁止使用构造方法的方式把值转化为BigDecimal对象。
说明:BigDecimal(double) 存在精度损失风险,在精确计算或值比较从场景中可能会导致业务逻辑异常。
如:BigDecimal a=new BigDecimal(0.1f)
;实际存储值为:0.10000000149
正例:优先推荐入参为String 的构造方法
,或者使用BigDecimal的valueOf方法
,此方法内部其实执行了Double的toString
,而Double的toString按Double的实际能表达的精度对尾数进行了截断。
BigDecimal recomment1 = new BigDecimal("0.1");
BigDecimal recomment2 = BigDecimal.valueOf(0.1);
4.注意Math.random()
这个方法返回的是double
类型,注意取值范围0<=x<1
(能够取值到零,注意除0异常),如果想获取整数类型的随机数,不要将x放大10的若干倍然后取整,直接使用Random
对象的nextInt
或者nextLong方法
。
Random r = new Random();
int a1 = r.nextInt();
long a2 = r.nextLong();