T31-Java代码避坑指南学习笔记

217 阅读7分钟

1. 浮点数数据的处理

浮点型
浮点数是属于有理数中某特定子集的数字表示,在计算机中用以近似表示任意某个实数
整形
计算机中的一个基本的专业术语,指没有小数部分的数据

任何货币金额,均以最小货币单位且整形类型来进行存储

image.png

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

单精度的存储示例5.2的存储

  1. 改写整数部分,先将整数部分十进制数改写成二进制101
  2. 小数部分,小数相当于2的-1一直到2的-N的和 .001100110011... 是一个无限循环的二进制数,所以十进制小数转换成二进制小数的时候会丢失精度 image.png
  3. 科学计数法规格化 将转换完成的二进制数据规格化,保持小数点前有且只有一个1
  4. 整数部分的填充 image.png
  5. 指数部分的填充

image.png

image.png

1.2 精确的小数存储-decimal

image.png

1.3 浮点数等值判断

基本数据类型不能用==来比较 包装数据类型不能用equals来判断 image.png

BigDecimal的等值比较应使用compareTo(),而不是equals()方法 equlas()方法比较值和精度(1.0 与1.00会返回fasle) compareTo() 会忽略精度 image.png 禁止使用构造方法BigDecimal(double)方法把double值转化为BigDecimal对象 image.png

2. 日期数据的处理

image.png

2.2 传统日期API的问题

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

2.3 JDK8新增API的优势

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

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

日期格式化时,传入pattern中表示年份统一实用小写y image.png 在日期格式中分清楚大写的M和小写的m,大写的H和小写的h分别指代的意义 image.png

2.5 获取当前毫秒数

image.png

3. 控制语句的避坑规范

3.1 控制语句之switch

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

3.2 控制语句规约

  1. 在if/else/for/while/do语句中必须使用大括号
  2. 表达异常的分支时,少用if-else方式
  3. 三目运算符高度注意类型对齐时,可能抛出因自动拆箱导致的NPE异常 image.png

image.png

3.3 控制语句好习惯

  1. 不要在其他表达式(尤其条件表达式)中,插入赋值语句
  2. 不要在条件判断中执行其他复杂的语句,以提高可读性
  3. 避免采用取反逻辑运算符,必须取反逻辑运算除外

3.4 在高并发场景中控制语句

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

image.png

3.5 需要参数校验的场合

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

3.6 不需要参数校验的场合

  1. 极有可能被循环调用的方法
  2. 底层调用频率比较高的方法
  3. 被声明成private image.png

4. 面向对象OOP设计

三个主要目标:可维护性、可重用性和可扩展性

4.1 面向对象四大特征

  1. 抽象(对需求进行业务抽象和建模分析,通过模型行为组合去共同解决某一类问题)
  2. 封装(封装是一种对象功能内聚的表现形式,使模块之间耦合度变低,更具有维护性)
  3. 继承(继承使子类能够继承父类,获得父类的部分属性和行为,使模块更有复用性)
  4. 多态(多态使模块在复用性基础上更加有扩展性,使系统运行更具有想象空间)

4.2 七大设计原则

1. 单一职责原则

最简单的,但是却是最难的。 高内聚、低耦合的延伸。 属性和行为向着模块预先定义的功能内聚,模块的名字非常重要 2. 里氏替换原则 鱼能游,鲨鱼能游,可以 反之,鲨鱼有牙齿,推导不出,鱼有牙齿 车能开,跑车能开,可以 反之,跑车的推背感很强,推导不出,车的推背感很强 父类能够出现的地方,自雷一定能够出现,这是里氏替换 而子类出现的地方,用父类去替代,一般都有问题

3. 接口隔离原则

接口的粒度尽可能的小,同一接口的方法强内聚于同一特征

4. 组合复用原则

继承是一种绑定关系,相当于父子关系 组合是一种松散的合作关系,相当于谈恋爱 组合产生的对象,方法暴露的少 继承产生的对象,继承线路上的方法全部暴露出来 增加用户的选择成本,容易误用

5. 依赖倒置原则

细节依赖抽象 底层依赖于高层 宪法不可能依赖于地方法律 我们的网络服务只依赖于协议,而不是具体的硬件

6. 迪米特原则

互相了解的信息,尽可能的少 你使用一个接口,你只关注,输入和输出,你不需要关注具体代码实现,你不需要关注具体代码实现 我么听歌时,我们也不需要关注内部芯片的处理,我们只关注接口是圆的,还是蓝牙的

7. 开闭原则

对扩展开放,对修改关闭 扩展能力主要是对需求继续变化的适应能力 代码最大的稳定性,一旦成功运行,就不应该具体的代码扩展 通过依赖倒置,实现增加类,或模块的方式,实现需求的变化 任何变化的点,都是需要被隔离出来的

架构师最大的难点,识别和隔离变化点

4.3 OOP规约

  1. 所有的覆写方法,必须加上@Override注解

4.4 可变参数

  1. 相同参数类型,相同业务含义
  2. 避免使用Object
  3. 可变参数必须放置在参数列表的最后
  4. 尽量不用可变参数

4.5 方法及属性

  1. 所有的POJO类属性必须使用包装数据类型
  2. 定义DO DTO VO 等POJO类时,不要设定任何属性默认值
  3. 定义数据对象DO类时,属性类型要与数据库字段类型相匹配
  4. getter/setter 方法中,不要增加业务逻辑
  5. 禁止在POJO类中,同时存在对应属性xxx的isXxx()和getXxx()方法
  6. 构造方法里禁止加入任何业务逻辑,如果有初始化逻辑,请放到init方法中