Double计算的处理

  1. // 遇到 浮点类型的 计算的时候 时候 BigDecimal 来进行计算 如果直接使用double 则会失精
  2. // 在使用 BigDecimal 的时候 需要将double类型 转成String类型 直接使用double类型 也会是失精
  3. BigDecimal bigDecimal = new BigDecimal("1.0212");
  4. BigDecimal bigDecimal1 = new BigDecimal("1.0201");
  5. System.out.println(bigDecimal.subtract(bigDecimal1).toString()); // 0.0011
  6. BigDecimal decimal = BigDecimal.valueOf(0.1111); // 另一种形式实现
  1. 8. 【强制】浮点数之间的等值判断,基本数据类型不能用==来比较,包装数据类型不能用equals来判断。 说明:浮点数采用“尾数+阶码”的编码方式,类似于科学计数法的“有效数字+指数”的表示方式。二进
  2. Java 开发手册
  3. 8/44
  4. 制无法精确表示大部分的十进制小数,具体原理参考《码出高效》。 反例: float a = 1.0f - 0.9f; float b = 0.9f - 0.8f; if (a == b) { // 预期进入此代码快,执行其它业务逻辑 // 但事实上a==b的结果为false } Float x = Float.valueOf(a); Float y = Float.valueOf(b); if (x.equals(y)) { // 预期进入此代码快,执行其它业务逻辑 // 但事实上equals的结果为false } 正例: (1) 指定一个误差范围,两个浮点数的差值在此范围之内,则认为是相等的。 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 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"); }
  5. 9. 【强制】定义数据对象DO类时,属性类型要与数据库字段类型相匹配。 正例:数据库字段的bigint必须与类属性的Long类型相对应。 反例:某个案例的数据库表id字段定义类型bigint unsigned,实际类对象属性为Integer,随着id越来越大,超过Integer的表示范围而溢出成为负数。
  6. 10. 【强制】为了防止精度损失,禁止使用构造方法BigDecimal(double)的方式把double值转化为BigDecimal对象。 说明:BigDecimal(double)存在精度损失风险,在精确计算或值比较的场景中可能会导致业务逻辑异常。如:BigDecimal g = new BigDecimal(0.1f); 实际的存储值为:0.10000000149 正例:优先推荐入参为String的构造方法,或使用BigDecimalvalueOf方法,此方法内部其实执行了DoubletoString,而DoubletoStringdouble的实际能表达的精度对尾数进行了截断。
  7. Java 开发手册
  8. 9/44
  9. BigDecimal recommend1 = new BigDecimal("0.1"); BigDecimal recommend2 = BigDecimal.valueOf(0.1);
  1. 【强制】浮点数之间的等值判断,基本数据类型不能用来比较,包装数据类型不能用equals来判断。 说明:浮点数采用“尾数+阶码”的编码方式,类似于科学计数法的“有效数字+指数”的表示方式。二进
    Java 开发手册
    8/44
    制无法精确表示大部分的十进制小数,具体原理参考《码出高效》。 反例: float a = 1.0f - 0.9f; float b = 0.9f - 0.8f; if (a == b) { // 预期进入此代码快,执行其它业务逻辑 // 但事实上ab的结果为false } Float x = Float.valueOf(a); Float y = Float.valueOf(b); if (x.equals(y)) { // 预期进入此代码快,执行其它业务逻辑 // 但事实上equals的结果为false } 正例: (1) 指定一个误差范围,两个浮点数的差值在此范围之内,则认为是相等的。 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 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”); }
  2. 【强制】定义数据对象DO类时,属性类型要与数据库字段类型相匹配。 正例:数据库字段的bigint必须与类属性的Long类型相对应。 反例:某个案例的数据库表id字段定义类型bigint unsigned,实际类对象属性为Integer,随着id越来越大,超过Integer的表示范围而溢出成为负数。
  3. 【强制】为了防止精度损失,禁止使用构造方法BigDecimal(double)的方式把double值转化为BigDecimal对象。 说明:BigDecimal(double)存在精度损失风险,在精确计算或值比较的场景中可能会导致业务逻辑异常。如:BigDecimal g = new BigDecimal(0.1f); 实际的存储值为:0.10000000149 正例:优先推荐入参为String的构造方法,或使用BigDecimal的valueOf方法,此方法内部其实执行了Double的toString,而Double的toString按double的实际能表达的精度对尾数进行了截断。
    Java 开发手册
    9/44
    BigDecimal recommend1 = new BigDecimal(“0.1”); BigDecimal recommend2 = BigDecimal.valueOf(0.1);

    关于基本数据类型与包装数据类型的使用标准如下

    强制:所有的POJO类属性必须使用包装数据类型
    强制:所有的RPC方法的返回值和参数必须使用包装数据类型
    推荐: 所有的局部变量使用基本数据类型

    说明:POJO类属性没有初值是提醒使用者在需要使用时,必须自己显式地进行赋值,任何NPE问题,或者入库检查,都由使用者来保证。
    正例:数据库的查询结果可能是null,因为自动拆箱,用基本数据类型接收有NPE风险。 反例:比如显示成交总额涨跌情况,即正负x%,x为基本数据类型,调用的RPC服务,调用不成功时,返回的是默认值,页面显示为0%,这是不合理的,应该显示成中划线。所以包装数据类型的null值,能够表示额外的信息,如:远程调用失败,异常退出。

关于POJO类型默认值

【强制】定义DO/DTO/VO等POJO类时,不要设定任何属性默认值。 反例:POJO类的createTime默认值为new Date(),但是这个属性在数据提取时并没有置入具体值,在更新其它字段时又附带更新了此字段,导致创建时间被修改成当前时间。

【强制】构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在init方法中。
【强制】POJO类必须写toString方法。使用IDE中的工具:source> generate toString时,如果继承了另一个POJO类,注意在前面加一下super.toString。

说明:在方法执行抛出异常时,可以直接调用POJO的toString()方法打印其属性值,便于排查问题。

split的 方法 关于末尾为空的时候

  1. String s="a,b,c,,";
  2. String[] split = s.split(",",-1); // 5 包含空值和空格
  3. String[] split1 = s.split(","); //3 不包含空值和空格
  4. System.out.println(split.length);

【推荐】使用索引访问用String的split方法得到的数组时,需做最后一个分隔符后有无内容的检查,否则会有抛IndexOutOfBoundsException的风险。
说明:
String str = “a,b,c,,”;
String[] ary = str.split(“,”);
// 预期大于3,结果是3
System.out.println(ary.length);