(四)改掉这些坏习惯,还怕写不出健壮的代码?

飞牛Docker部署Zerotier后无法访问?三步搞定SSH权限配置! 本文详细解析了在飞牛NAS上通过Docker部署Zerotier后无法访问的常见问题及解决方案。重点介绍了SSH权限配置、tun模块加载和Docker容器权限设置等关键步骤,帮助用户快速解决虚拟网络接口的权限问题,确保Zerotier节点间的正常通信。 阅读详情

Code Review 是一场苦涩但有意思的修行。

(一)改掉这些坏习惯,还怕写不出健壮的代码?

(二)改掉这些坏习惯,还怕写不出优雅的代码?

(三)改掉这些坏习惯,还怕写不出优雅的代码?

书接上篇,本次继续探讨一下,该如何写出健壮的代码?

1. 编码时:看似顺眼,实则不然。 

举个栗子:

String amount = request.getParameter("amount");
// 校验金额小数点后最多两位小数
BigDecimal a = new BigDecimal(amount);
if (a.doubleValue() * 100 - Math.floor(a.doubleValue() * 100) != 0) {
    System.out.println("交易金额错误");
    // do something ... ...
}

摘一段跑在生产环境上的代码,代码咋一看没啥问题,主要功能是获取请求参数;然后完成数据校验。

看似很顺眼,但是你细品,就会发现其中之奥秘,下面一起在本地跑跑代码,来分析一下到底会存在什么问题?

问题一:坑死人的 NPE

输入:null(当 amount 输入为空时)

输出:

Exception in thread "main" java.lang.NullPointerException
  at java.math.BigDecimal.<init>(BigDecimal.java:806)
  at PayController.main(PayController.java:300)

分析:

根据上面异常信息,见 BigDecimal 的源码第 806 行,如下图所示,很显然 BigDecimal 构造不会判断传入的 val 是否为空,所以会出现空指针异常。

目前没有出现问题,那只能算庆幸,不过终究是个定时炸弹。切记调用 BigDecimal 的构造时,请勿传入 null 值。

心声:

身边老码农真真的排查了好长时间,问题场景与此类似,直接阻断了程序后续的流程。

问题二:同样是传入数字,结果咋就匪夷所思。

输入:

6666.66(当 amount 输入为 6666.66)

当 amount 输入为 6666.66 时,amount 的值校验通过。真的是看到的这个样子吗?换个数试试呗。

输入:

8888.88(当 amount 输入为 8888.88)
‍

输出:

交易金额错误

分析:

容我拆解一下代码,当 amount 传入为 8888.88 时:

double d1 = a.doubleValue() * 100;
double d2 = Math.floor(a.doubleValue() * 100);
System.out.println(d1); // 输出:888887.9999999999
System.out.println(d2); // 输出:888887.0
System.out.println(d1 - d2); // 输出:0.9999999998835847

很显然, d1 - d2 的值 != 0,那么如下表达式的值则满足,会输出交易金额错误。

为什么呢?归根揭底是 double 运算时精度丢失而导致程序处理出错,虽然在 Java 中提倡用 BigDecimal 进行四则运算,但是上面的校验实现,貌似跟 BigDecimal 没有啥关系,到底该怎么解决呢?

无脑实现方式:

if (amount.contains(".") && amount.substring(amount.indexOf(".") + 1).length() > 2) {
      System.out.println("校验失败 2");
      // do something ... ...
}

如上面代码段所示,直接判断传入的 amount 字符串小数点后面的位数就可以啦。

当然,仁者见仁智者见智,实现方式有很多,不去多深究。

2. 编码时:时间转换也作祟 

举个栗子:

public static long convertDaysToMilliseconds(int days) {
    return 1000 * 3600 * 24 * days;
}

分析:

1000 * 3600 * 24 * days 结果默认为 int 类型,最大值为 2147483647,如果超过 int 范围,则会出现截断,程序不会出错,但是结果却匪夷所思。

例如:

当 days 输入为 30 时,程序输出:-1702967296。

改进方式一:

改进方式二:

再举个栗子:

public static Date getDate(int seconds) {
    return new Date(seconds * 1000);
}

分析:

当 seconds * 1000 值为 int 类型,当超过 int 最大值为2147483647 时,程序不会出错,但是结果却匪夷所思。

改进方式:

分享一下心声:

  • 禁止使用 double 直接参与金额运算,会出现意想不到的结果。

浮点数采用“尾数+阶码”的编码方式,类似于科学计数法的“有效数字+指数”的表示方式。 二进制无法精确表示大部分的十进制小数。

—— 请自行科普,留作业。

  • 禁止使用构造方法 BigDecimal(double)的方式把 double 值转化为 BigDecimal 对象。

BigDecimal(double)存在精度损失风险,在精确计算或值比较的场景中可能会导致业务逻辑异常。 

如:BigDecimal g = new BigDecimal(0.1f); 实际的存储值为:0.10000000149 

优先推荐入参为 String 的构造方法,或使用 BigDecimal 的 valueOf 方法,此方法内部其实执行了 Double 的 toString,而 Double 的 toString 按 double 的实际能表达的精度对尾数进行了截断。

—— 阿里开发手册

  • 那些看似顺眼的代码,或者线上跑着的代码,未必就没问题,只是没有走到异常分支上去,随着时间的推移,定时炸弹迟早会爆,定期审查代码,以及充分的测试是非常的必要。

3. 寄语写最后 

我等采石之人当心怀大教堂之愿景——《程序员修炼之道》。

好了,代码修炼的系列分享,本次就谈到这里,一起聊技术、谈业务、喷架构,少走弯路,不踩大坑。会持续输出原创精彩分享,敬请期待!

推荐阅读:

(一)改掉这些坏习惯,还怕写不出健壮的代码?

(二)改掉这些坏习惯,还怕写不出优雅的代码?

(三)改掉这些坏习惯,还怕写不出优雅的代码?

PX4从放弃到精通(十九):串口驱动 文章目录前言一、创建进程二、编写驱动 前言 硬件: PIXHAWK4 USB转串口模块 软件: Ubuntu18.04 PX4 1.11.3固件 QGC地面站 串口助手 一、创建进程 参考:https://mbot1.blog.youkuaiyun.com/article/details/122587617 二、编写驱动 ......... 阅读详情

相关推荐

概率论 知识图谱 + 实战案例解析

本文通过构建概率论知识图谱,系统梳理了从随机试验、概率、条件概率到随机变量与分布的核心概念及其内在联系。结合朴素贝叶斯分类器和蒙特卡洛模拟等实战案例,深入解析了条件概率、独立性及大数定律等理论如何应用于机器学习与实际问题求解,旨在帮助读者建立结构化思维,将理论有效转化为解决实际问题的能力。

weixin_29051193的博客 267

为什么很多学习Java的人能看懂代码,但自己动手确写不出来?

关于这个问题,想必是很多人都有的心理历程或者是“说辞”,但其实真正的原因并不是你们所说的“我能看懂,但是让我写却写不出来”,真正的原因和问题是在于你当时学习的时候就没有学会,也不懂如何正确的学习Java编程。根据这个问题的具体原因以及如何去破解这样的问题,我今天会在下面跟大家详细说明。 “我能看懂代码,但是让我自己写却写不出来”,这样的话在我刚开始的时候自己也说过,但后来会写代码之后,会发现这样的说法是没过脑子的,也没有仔细去探究一下根本原因是什么,“能看懂”这样的说法可以说是记忆好,或者是对于英语懂一些,

Teacher_Zhan的博客 4445

陀螺仪选型避坑指南:为什么IMU660RA是智能车竞赛的性价比之选?

本文针对智能车竞赛场景,提供陀螺仪选型避坑指南,并深度解析为何IMU660RA成为性价比之选。文章指出,竞赛选型应避免盲目追求高性能“黑盒”模块,而应注重原始数据获取与算法开发。IMU660RA以其良好的常温稳定性、适中的噪声水平、极致的性价比和丰富的生态支持,成为帮助参赛者深入理解姿态解算原理、进行“白盒开发”的理想教学与实践平台。

tech5的博客 880

当程序员写不出代码了,我该怎么办?

你已经对着电脑n个小时了。不知道该写什么代码,或者一种摔键盘的冲动正在你的胸中酝酿。 可乐一瓶接着一瓶。不敢再喝了,因为搞不好要有副作用了,心跳加速,身体不由自主地颤抖,出冷汗,但还是无法产出任何代码。 编程的本质是棘手 即使是最优秀的程序员也会遭遇无法解决的软件工程问题。碰到这样的问题,并不一定意味着你缺乏技能或知识。 编程不是一项容易的工作,我们

qq_37508157的博客 641

人工智能面试总结-Python

B站:啥都会一点的研究生 公众号试读:啥都会一点的研究生 目录说说Python程序运行过程?说说Python的作用域?说说Python的数据结构?说说Python中可变与不可变类型?说说进程与线程?说说Python中的多线程?说说Python中的多进程?说说Python互斥锁与死锁?说说Lambda?说说Python的深拷贝与浅拷贝?说说Python多线程是否能用多个CPU,为什么?说说Python垃圾回收机制?说说Python里的生成器?说说迭代器与生成器的区别?说说Python 列表的 del,rem.

啥都生的博客 1万+

YOLO26全网首发:CVPR2026 MixerCSeg | DEGConv方向引导边缘门控,破解细长裂缝检测难题

DEGConv通过方向先验嵌入、边缘增强卷积和动态门控三大机制,针对性解决了YOLO在处理裂缝类细长、多方向、低对比度目标时的特征提取不足问题,显著提升了裂缝检测的精度与鲁棒性。

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 1034

java十进制小数转化为二进制小数代码 乘二取整法_(四)改掉这些坏习惯,还怕写不出健壮的代码?...

Code Review 是一场苦涩但有意思的修行。(一)改掉这些坏习惯,还怕写不出健壮的代码?(二)改掉这些坏习惯,还怕写不出优雅的代码?(三)改掉这些坏习惯,还怕写不出优雅的代码?书接上篇,本次继续探讨一下,该如何写出健壮的代码?1编码时:看似顺眼,实则不然。举个栗子?:String amount = request.getParameter("amount");// 校验金额小数...

weixin_29284201的博客 355

Pandas滚动窗口的妙用:动态计算列数据的最大值

Pandas的滚动窗口(rolling window)功能是数据分析中处理时间序列数据的重要工具。本文通过实例演示了如何使用rolling(window=4).max()计算DataFrame列A的滚动最大值,并将结果存入新列Max_Range。该方法会在4个元素的滑动窗口内计算最大值,前3行因数据不足显示为NaN。这种技术广泛应用于金融分析(如股价波动)、数据平滑和趋势识别等场景,能有效帮助分析数据的动态变化特征。示例展示了从数据准备到结果输出的完整流程,体现了Pandas在处理滑动窗口计算时的高效性和便

m0_74337424的博客 53

用BigDecimal的时候报错NullPointerException

用BigDecimal的时候报错NullPointerException

Dragon_Python的博客 1706

华为OD机试真题 新系统【Skill执行链完整性检测】

华为OD机试 新系统真题【Skill执行链完整性检测】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。华为OD机试真题【Skill执行链完整性检测】

qq_45776114的博客 763

ESD防护设计宝典(十九):元器件选型宝典——共模电感

然而,这位“大师”的脾气也颇为古怪,若设计者不解其性、用之不当,它非但不能抑制噪声,反而会引入信号完整性恶化、电源压降等新问题,甚至让您的系统EMC性能“雪上加霜”,导致项目在测试阶段功亏一篑。本文将带您深入共模电感的内在世界,从本质解析到参数详解,从设计陷阱到实战选型,全方位领悟其平衡艺术,掌握其应用核心,规避那些足以让项目翻车的致命陷阱。:这是存在于电路板内部的“家贼”。共模电感实质上是一个四端器件,它通过磁场的“加法”与“减法”运算,巧妙地实现了对共模噪声的抑制,同时为差模信号大开绿灯。

m0_56451176的博客 421

java.lang.NumberFormatException at java.math.BigDecimal.<init>

java.lang.NumberFormatException   at java.math.BigDecimal.   表中字段对应的类型  注意小数点的位数 2.接受数据转换时,小心null值,以及接受的数据类型百分号的。

wdgkw的专栏 1万+

硅基半导体量子点:单电子自旋量子比特技术手册

现在我们已经了解了从硅片到容错计算的全部环节,让我们用一张总览图把碎片拼成完整拼图。fill:#333;important;important;fill:none;color:#333;color:#333;important;fill:none;fill:#333;height:1em;important;important;important;color:#000!important;important;important;important;important;color:#000!

VectorShift的博客 371

(四)改掉这些坏习惯,还怕写不出健壮的代码?(转载)

Code Review 是一场苦涩但有意思的修行。 (一)改掉这些坏习惯,还怕写不出健壮的代码? (二)改掉这些坏习惯,还怕写不出优雅的代码? (三)改掉这些坏习惯,还怕写不出优雅的代码? 书接上篇,本次继续探讨一下,该如何写出健壮的代码? 编码时:看似顺眼,实则不然。 举个栗子: String amount = request.getParameter(“amount”); // 校验金额小数点后最多两位小数 BigDecimal a = new BigDecimal(amount); if (a.d

shuirenbushijun的博客 177

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

java入职写不出代码_(四)改掉这些坏习惯,还怕写不出健壮的代码?

Code Review 是一场苦涩但有意思的修行。书接上篇,本次继续探讨一下,该如何写出健壮的代码?编码时:看似顺眼,实则不然。 举个栗子:String amount = request.getParameter("amount");// 校验金额小数点后最多两位小数BigDecimal a = new BigDecimal(amount);if (a.doubleValue() * 100 - ...

weixin_39997173的博客 191

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

(一)改掉这些坏习惯,还怕写不出健壮的代码?

Code Review 是一场苦涩但有意思的修行。近期对团队负责的项目,进行了一次 Code Review,代码评审过程中遇到的那些编码坏习惯,笑的合不拢嘴。不过,评审中很多代码编写问题...

一猿小讲 3874

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

(六)改掉这些坏习惯,还怕写不出精简的代码?

鲁迅说:嬉笑怒骂里充满了无奈和妥协。小猿说:先生说的不对,在程序员的世界里,编写代码处处充满了无奈和妥协。(一)改掉这些坏习惯,还怕写不出健壮的代码?(二)改掉这些坏习惯,还怕写不出优...

一猿小讲 1850

(二)改掉这些坏习惯,还怕写不出优雅的代码?

Code Review 是一场苦涩但有意思的修行。上期分享,通过示例剖析编码中一些经常触犯的性能点,以及编码时常犯的一些小毛病,来告诉新手程序员如何写出健壮的代码。咱们书接上篇,本次一起...

一猿小讲 1625

前端写TypeScript的时候必须改掉的 16 个坏习惯

​:用 JSDoc 或 TSDoc 描述复杂逻辑。​:显式声明返回值类型,便于维护和文档化。​:假设 API 返回的数据符合预期。​:用注释掩盖问题,而非修复类型错误。​:优先解决类型问题,或使用更安全的。​:依赖类型推断,函数返回值不明确。​:直接使用字符串/数字,难以维护。​:将类型抽离到单独文件(如。​:手动维护类型与值的同步。​:类型定义与业务代码混杂。​:代码缺乏文档,难以理解。​:使用类型守卫或库(如。​:用泛型抽象通用逻辑。​:未穷举所有条件分支。​:用枚举或常量替代。

W11929311582的博客 586

(五)改掉这些坏习惯,还怕写不出精简的代码?

鲁迅说:嬉笑怒骂里充满了无奈和妥协。小猿说:先生说的不对,在程序员的世界里,编写代码处处充满了无奈和妥协。Code Review 是一场苦涩但有意思的修行。(一)改掉这些坏习惯,还怕写...

一猿小讲 1976

(三)改掉这些坏习惯,还怕写不出优雅的代码?

Code Review 是一场苦涩但有意思的修行。书接上篇,本次一起继续探讨一下,该如何写出优雅的代码?1编码时:搞的复杂并不好坏习惯一:多余的 if/else。反例:类似上面这种写...

一猿小讲 2036

改掉这些坏习惯,还怕写不出精简的代码

鲁迅说:嬉笑怒骂里充满了无奈和妥协。 小猿说:先生说的不对,在程序员的世界里,编写代码处处充满了无奈和妥协。 (一)改掉这些坏习惯,还怕写不出健壮的代码? (二)改掉这些坏习惯,还怕写不出优雅的代码? (三)改掉这些坏习惯,还怕写不出优雅的代码? (四)改掉这些坏习惯,还怕写不出健壮的代码? (五)改掉这些坏习惯,还怕写不出精简的代码? 上次讨论了一下如何借助注解来精简代码,代码修炼的系列分享,书接上篇,本次继续探讨一下:还有哪些奇淫技巧,能助力写出精简的代码? 1 编...

slw20010213的博客 195

从低效到高效:TypeScript 开发中必须改掉的 5 个坏习惯

在 TypeScript 开发中,改掉这些坏习惯,能让我们更好地利用 TypeScript 的特性,编写出更健壮、更易维护的代码。从避免过度使用any类型,到充分利用接口、泛型、类型推断等特性,每一个改变都将提升我们的开发效率和代码质量。让我们在 TypeScript 的世界里,不断优化编程习惯,创造出更优秀的前端应用。到这里,这篇文章就和大家说再见啦!我的过往文章里还藏着许多干货,感兴趣的话也可以点击我的主页看看,下面的文章也很精彩,可别错过。💕。

前端开发探索之旅 996

(五)改掉这些坏习惯,还怕写不出精简的代码?(转载)

鲁迅说:嬉笑怒骂里充满了无奈和妥协。 小猿说:先生说的不对,在程序员的世界里,编写代码处处充满了无奈和妥协。 Code Review 是一场苦涩但有意思的修行。 (一)改掉这些坏习惯,还怕写不出健壮的代码? (二)改掉这些坏习惯,还怕写不出优雅的代码? (三)改掉这些坏习惯,还怕写不出优雅的代码? (四)改掉这些坏习惯,还怕写不出健壮的代码? 代码修炼的系列分享,书接上篇,本次探讨一下:该如何利用注解写出精简的代码? 编码时:重复的校验,随处可见。 举个栗子: 再举个栗子: 如栗子示意,项目中参数校验随

zhongqill的博客 180

TypeScript 必须改掉的 10 个坏习惯

随着 TypeScript 生态系统的进一步成熟,有些你以前觉得合理的做法,现在可能不太合理。接下来,我将分享10 个常见的 TypeScript 坏习惯,并告诉你如何改进它们,确保你的代码更健壮、性能更高、并且更加易于维护。依赖隐式类型检查而非明确的类型保护,可能导致你错过一些重要的类型问题。

csdn_wzq的博客 1202

直接输出代码_(二)改掉这些坏习惯,还怕写不出优雅的代码?

Code Review 是一场苦涩但有意思的修行。上期分享,通过示例剖析编码中一些经常触犯的性能点,以及编码时常犯的一些小毛病,来告诉新手程序员如何写出健壮的代码。咱们书接上篇,本次一起来探讨一下,该如何写出优雅的代码?编码时:少一点不行 坏习惯一:记录日志时,缺失参数。反例:正解:1. 日志打印时,占位符 {} 要严格与参数相对应,如果对应不上,按照截图示意,日志输出则不会打印 queryStr...

weixin_42509708的博客 102
上一篇: (三)改掉这些坏习惯,还怕写不出优雅的代码?
下一篇: (五)改掉这些坏习惯,还怕写不出精简的代码?
一猿小讲
博客等级 码龄15年 294粉丝 156原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值