2021.11.9 孤尽训练营D15——java代码避坑指南

大纲:浮点数据的处理、日期数据的处理、控制语句的避坑规范、优雅的面向对象

浮点数据处理:

在计算机中,用浮点数近似表示任意某个实数,它无法精确表示一个数据,整型数据才可以精确表示一个值。

货币数据类型的选择:任何货币金额均以最小货币单位且整型类型来进行存储。

0.1默认是double类型

浮点数据类型的问题:精度丢失

单精度存储示例:(5.2)

  • 首先转换整数部分,即 5 变成二进制101
  • 小数部分相当于是2^(-1)一直到2^(-N)的和

 

  • 乘二取整法:我们可以把十进制的小数部分乘以2,取整数部分作为二进制的一位,剩余小数继续乘以2,直至不存在剩余小数为止。

2021.11.9 孤尽训练营D15——java代码避坑指南_第1张图片

规格化:5.2转换成二进制即101.00110011001100110011,然后将转换完成的二进制数据规格化,保持小数点前有且只有一个“1”,变成1.0100110011001100110011 *  2^2

指数部分的填充: 

2021.11.9 孤尽训练营D15——java代码避坑指南_第2张图片

 补充说明:2021.11.9 孤尽训练营D15——java代码避坑指南_第3张图片

 精确的小数存储使用decimal

MySQL:decimal(M,D) ------>  JAVA: JAVA.math.BigDecimal类

浮点数据避坑:

(一)浮点数之间的等值判断,基本数据类型不能用==来判断,包装数据类型不能用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的等值比较应使用compareTo()方法,而不是equals()方法

equals():方法会比较值和精度(1.0与1.00返回结果为false)

compareTo():会忽略精度

2021.11.9 孤尽训练营D15——java代码避坑指南_第4张图片

 (三)禁止使用构造方法BigDecimal(float)的方式把double值转换为BigDecimal对象

2021.11.9 孤尽训练营D15——java代码避坑指南_第5张图片

 

日期数据类型处理

2021.11.9 孤尽训练营D15——java代码避坑指南_第6张图片

 传统日期API的问题:

  • 所有日期类型都是线程不安全的
  • 日期、时间、时间戳没有明确对应的类,都是Date
  • 对于格式化和解析的需求,都是使用SimpleDateFormat类

 JDK8新增API的优势:

2021.11.9 孤尽训练营D15——java代码避坑指南_第7张图片

 日期格式化需要注意的问题:

(一)日期格式化时,传入patten中表示年份统一使用小写的y

  • 小写yyyy:表示当天所在的年
  • 大写YYYY:代表是week in whick year(JDK7之后引入的概念),意思是当天所在的周属于的年份,有可能出现跨年的情况

2021.11.9 孤尽训练营D15——java代码避坑指南_第8张图片

(二)注意分辨M、m,H、h

  • 表示月份是大写的M
  • 表示分钟则是小写的m
  • 24小时制的是大写的H
  • 12小时制的则是小写的h、

2021.11.9 孤尽训练营D15——java代码避坑指南_第9张图片

(三) 获取当前毫秒数:

System.currentTimeMills();而不是new Date().getTime()

如果想获取更加精确的纳秒级时间值,使用System.nanoTime的方式

在JDK8中,针对统计时间等场景,推荐使用Instant类

控制语句的避坑

控制语句之switch

  • 每个case要么通过continue / break / return等来终止
  • 要么注释说明程序将继续执行到哪一个case为止
  • 在一个switch块内,都必须包含一个default语句并且放到最后
  • 当switch括号内的变量类型为String并且此变量为外部参数时,必须先进行null判断

控制语句规约(一)

在 if / else / for / while / do语句中必须使用大括号

表达异常的分支时,少用 if-else方式

if 的嵌套不要超过三层

控制语句规约(二)

2021.11.9 孤尽训练营D15——java代码避坑指南_第10张图片

在高并发场景中控制语句规约

在高并发场景中,避免使用“等于”判断作为中断或退出的条件,如果并发控制没有处理好,容易产生等值判断被“击穿”的情况,使用大于或小于的区间判断条件来代替

需要参数校验的场合

  • 调用频次低的方法
  • 执行时间开销很大的方法。此情形中,参数校验时间几乎可以忽略不计,但如果因为参数错误导致中间执行回退,或者错误,那得不偿失
  • 需要极高稳定性和可用性的方法
  • 对外提供的开放接口,不管是RPC / API / HTTP接口
  • 敏感权限入口
  • 公开接口需要进行入参保护,尤其是批量执行的接口

不需要参数校验的场合

  • 皆有可能被循环调用的方法
  • 底层调用频度比较高的方法(比如DAO层的参数校验,可以忽略)
  • 被声明成private

OOP(面向对象编程)

 面向对象四大特征:抽象、封装、继承、多态

OOP规约:

  • 所有的覆写方法,必须加@Override注解
  • 尽量不用可变参数。用的话要尽可能保证相同参数类型,相同业务含义,避免使用Object;可变参数必须放置在参数列表的最后;
  • 对象的比较:
  1. 所有整型包装类对象之间值得比较,全部使用equals方法比较
  2. 应使用常量或确定有值的对象来调用equals,或java.util.Objects#equals(Object a,Object b)
  • 方法及属性:
  1. 所有的POJO类属性必须使用包装数据类型(可以为空;基础数据类型有默认值)
  2. 定义DO / DTO / VO 等POJO类时,不要设定任何属性默认值
  3. 定义数据对象DO类时,属性类型要与数据库字段类型相匹配
  4. getter / setter 方法中,不要增加业务逻辑
  5. 禁止在POJO类中,同时存在对应属性 xxx 的 isXxx () 和 getXxx () 方法
  6. 构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在init方法

你可能感兴趣的:(笔记,java,开发语言,后端)