孤尽训练营打卡日记day16--Java代码避坑指南

孤尽训练营打卡日记day16--Java代码避坑指南,第1张

孤尽训练营打卡日记day16--Java代码避坑指南 前言

 

        在我们日常开发中,代码有很多细节都是我们不曾注意的,比如金额应该使用 double 还是 float,或者是int;时间格式化里的yyyy代表什么,使用 大写YYYY 行不行。很多东西我们一直都是看前人这么写的,我们就跟着写,没考虑过为什么。今天,跟着无尘老师我们一下学习一下代码中一些常见的坑。

浮点数据处理

浮点型:double、float

        浮点数是属于有理数中某特定子集的数字表示,在计算机中用以近似表示任意某个实数

整型:int

        计算机中的一个基本的专业术语指没有小数部分的数据

应用场景:

        货币数据类型的选择:最小货币单位且整型进行存储

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

浮点数使用科学计数法存储

单精度数存储格式:float

浮点数在计算机的存储: 5.2

整数部分:先将整数部分改写成二进制

5 => 101

小数部分:是 2 的负一次方一直到 2 的负n次方和

0.2在十进制转二进制的时候,是一个无限不循环的二进制数,所以十进制在转二进制的时候会丢失精度

二进制转换后:

101.00110011001100110011

保持小数点前面有且只有一个1

 1.0100110011001100110011

最终结果:

有效数字填充:整数部分的1舍去,也就是

 01001100110011001100110

指数部分填充

  • 在符号位右侧分配8位来存储指数
  • 阶码位存储的是指数对应的移码,是将一个真值在数轴上正向平移一个偏移量之后得到的
  • 移码的意义是把真值映射到一个正数域,可以直观地反应两个真值的大小,即移码大的真值也大

  移码公式:                           

其中2 的n-1 次方 减1 是IEEE754标准规定的偏移量

在float中的n为8,x移 = x + 127 = 129,二进制为 1000 0001

精确的小数存储-decimal (M,D)

M:指定小数点左边和右边可以存储的十进制数字的最大个数,MySQL中的范围 1~65

D:指定小数点右边可以存储的十进制数字的最大个数。小数数位必须小于M,默认的小数位数为0

Java:java.math.BigDecimal 类

浮点数据避坑:

  • 浮点数之间的等值判断,基本数据类型不能用 == 来比较,包装数据类型不能使用 equals 来判断
  • BigDecimal的等值比较应使用 compareTo() 方法,而不是equals() 方法
  • equals() 方法会比较值和精度(1.0 和 1.00 比较会返回false),compareTo会忽略精度
  • 禁止使用构造方法 BigDecimal(double) 的方式把 double 值转化为 BigDecimal对象

日期数据处理

Java中传统日期API

Date:表示特定瞬间,精确到毫秒

SimpleDateFormat:继承DateFormat类,主要用来格式转化

Calendar:一个工具类,为特定瞬间和一组日历字段之间的转换以及 *** 作日历字段提供了方法

Java 8新增日期API

LocalDate:代表日期

LocalTime:代表时刻

LocalDateTime:代表具体时间

Instant:代表时间戳

传统API 问题

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

JDK8 新增API的优势

  • 不变性:线程安全
  • 关注点分离:时间日期都有对应的类
  • 清晰:在所有的类中,方法都被明确定义用以完成相同的行为
  • 实用 *** 作:所有新的日期/时间API类都实现了一系列方法用以完成通用的任务

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

  • yyyy    表示当天所在的年
  • YYYY 表示当前周所在的年,如果本周跨年,返回的YYYY就是下一年
  • M 月份
  • m 分钟
  • H 24小时制
  • h 12小时制
  • 获取当前毫秒数,使用System.currentTimeMillis() ,而不是 new Date().getTime()

控制语句避坑规范

Switch

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

三目运算符高度注意类型对齐时,可能抛出因自动拆箱导致的NPE异常

触发场景

  • 表达式 1 或表达式 2 的值只要有一个是原始类型
  • 表达式 1 和 表达式 2 的值类型不一致,会强制拆箱升级成表示范围更大的那个类型
int a = 1;
Integer b = 2;
Integer c = null;
Boolean flag = false;
// a * b 结果是 int类型,那么c会强制拆箱成int类型,抛出NPE
Integer result = (flag ? a * b : c)
  • 不要在其它表达式中,插入赋值语句,比如条件表达式,因为很容易忽略这个值已经改变
  • 不要在条件判断中执行其它复杂的语句,以提高可读性
  • 避免采用取反逻辑运算符

高并发场景中的语句规约

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

需要参数校验的场合

  • 调用频次低的方法
  • 执行时间开销很大的方法
  • 需要极高稳定性和可用性的方法
  • 对外提供的开放接口,不管是 RPC/AP/HTTP 接口
  • 敏感权限入口
  • 公开接口需要进行入参保护,尤其是批量 *** 作的接口

不需要参数校验的方法

  • 极有可能被循环调用的方法
  • 底层调用频率比较高的方法
  • 被声明成 private

种树的最好时间是十年前,其次是现在!

参考文档:无尘老师PPT

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5437614.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-11
下一篇 2022-12-11

发表评论

登录后才能评论

评论列表(0条)

保存