本博文为《编写高质量代码—改善Java程序的151个建议》一书的阅读笔记。该书从很多方面给予了编写高质量代码的宝贵经验。而且该书应该是那种开发经验越丰富,体会越深的书籍。在阅读过程中,从该书中收获良多,这里主要作下书籍笔记,有体会的地方加点自己的想法。受限于知识水平,部分内容还没能深刻体会,所以更多更好的内容和具体实例还需要从书中去找寻。
一、不要用浮点数处理货币
货币在单位是元的时候常常都是带小数的,比如角分。这时候货币的数值就是小数,有些系统为了定义方便,直接定义成float或者double类型,然后运算运算就发现数据不对劲了,小数位总好像差点。我前两个月接手了一个老系统就是这样,非常地坑。
浮点数由于是二进制存储,对于部分小数根本无法准确表示,只能是近似存储,因此在运算过程中可能出现“意外”的结果。所以对于小数的定义,尤其是涉及到货币相关的处理,数据类型最好定义成BigDecimal,这是专门为了弥补浮点数无法精确计算而设计的类。另外还有种思路是先将小数放大成整数,再作运算。
以个人的经验,认为定义成BigDecimal最佳,放大成整数还要放大缩小,多一些多余的操作,字段的含义也发生了变化。
二、不要让类型默默转化
在数据类型默认转化时可能出现意想不到的Bug,例如书中所举的例子:long dis = 30 * 10000 * 1000 * 60 * 8;结果dis的值是个负数(-2028888064),因为dis右边运算的结果是Int类型,但是超过最大长度了,所以变成了负值(越界从头算起)。
这种int类型默默转换成long类型可能就会出现问题,所以尽量避免默认转换,比如上面的例子可以在30后面加L,让计算结果为long类型。
三、边界,还界,还是边界
在代码编写的过程中一定要考虑数据类型的边界,不然可能出现意想不到的问题。比如书中所举的例子int order = 用户输入的订单数,if( order >0 && order+1000<=2000 )就预定成功,这段逻辑初看起来没有任何问题,可是如果order=2147483674竟然可以预定成功。根据原因就是因为order=2147483674时再加1000就已经超过Int最大值,得到负数肯定比2000小。
所以在编写程序一定要注意边界值,另外单元测试时也要做边界测试,假如输入参数是int类型,就要考虑正最大、负最小、0这些边界值。
四、不要让四舍五入亏了一方
四舍五入是一种常见的计算方法,通常的做法都是小数位小于等于4则舍弃,大于等于5则进位后舍弃。但是这种算法对于银行的利息计算就会出现亏损,书中举了个非常好的例子,结论是考虑银行存款足够多,数字均匀发布的情况下每10笔利息银行就会亏损0.005元。
所以在类似银行利息计算的时候,需要使用修正的四舍五入算法,即银行家舍入近似算法,具体规则为:
1. 舍入位小于5直接舍弃;
2. 舍入位数值大于等于6则进位后舍弃;
3. 舍入位等于5时,若5后面还有其它非0数字,则进位后舍弃,若5后面是0(或最后一个数字),则根据5前一位的奇偶性判断是否需要进位,奇数则进位,偶数则舍弃。
简言之,就是四舍六入五考虑,五后非零则进一,五后为零看奇偶,五前为偶应舍弃,五后为奇要进一。
使用银行家的舍入算法,可以通过设置舍入模式为RoundingMode.HALF_EVEN实现。在普通项目中舍入模式不会有太大影响,可以直接使用Math.round方法,但是在大量与货币数字交互的项目中,则需要根据场景选择合适的舍入算法了(RoundingMode有多种舍入模式)。
五、提防包装类型的null值
包装类型在参与运算时要做null值校验,不然若包装类型为空,取值运算时会抛出空指针异常。因此为了程序的健壮性考虑,运算时需做校验。
六、谨慎包装类型的大小比较
包装类型不要直接通过比较运算符(>,<,=)进行比较,因为包装类型是对象应该通过compareTo就去进行比较。
七、优先使用整型池
通过包装类的valueOf生成包装实例可以显著提高空间和时间性能,以Integer为例,Integer会有一个内部的缓存,缓存-128到127之间的对象,而使用valueOf方法生成实例时,如果在范围内就直接返回缓存的对象了,这样就提高了性能。
另外包装类型进行相等判断时最好使用equals,而非==。
八、优先选择基本类型
无论从安全性、性能、稳定性考虑,基本类型相比于其对应的包装类型都是应该优先考虑选用的类型。
九、不要随便设置随机种子
在Java项目中,通常使用Math.random方法和Random类来生成随机数,其中Random类可以设置随机数种子,而一旦设置随机数种子,则在同一台机器 上不论运行多少次随机数总是相同的。因为随机数与种子有如下规则:
1. 种子不同,随机数不同;
2. 种子相同,即使实例不同,也产生相同的随机数。
而Random的默认构造类,种子是seedUniquifier() ^ System.nanoTime(),这样保证了种子的不同。所以想生成“真正的”随机数,不要随便设置随机种子。
十、正确使用String、StringBuffer、StringBuilder
三种字符序列的不同使用场景:
1. String类:由于String对象是不可变的,所以String类应该在字符串不经常变化的场景中使用,例如常量的声明、少量变量运算等。
2. StringBuffer类:在频繁进行字符串运算(如拼接、替换、删除等),而且运行在多线程环境中时,应该考虑使用StringBuffer,例如XML解析、HTTP参数解析和封装。
3. StringBuilder类:在频繁进行字符串运算(如拼接、替换、删除等),而且运行在单线程环境中时,应该考虑使用StringBuilder,如SQL语句的拼装、JSON封装。
相关推荐
综上所述,《编写好质量代码》这本书中的建议涵盖了从数据类型的选择到程序控制语句的优化等多个方面,对于希望编写高质量C程序的开发者来说非常实用。遵循这些建议可以帮助开发者编写出更加安全、健壮、高效的代码...
高质量编程是软件开发中至关重要的一个方面,它涉及到代码的可读性、可维护性、效率和可靠性。本指南基于C++/C语言,由林锐博士编写,旨在提供一套规范和最佳实践,以确保代码的质量。 **前言** 高质量的编程始于对...
这份指南首先会引导读者理解C++的基本语法,如变量、数据类型、控制结构(如if语句和循环)、函数以及类的概念。这些基础知识是编写任何程序的基础,也是理解和使用C++其他特性的重要前提。 C++的强项在于它的面向...
一本高质量的高分笔记往往由经验丰富的考研辅导老师或高分考生编写,他们能够提供专业且针对性的学习指导。笔记中的内容通常包括了考点讲解、易错点提示、习题解析等,对考生来说具有很高的参考价值。 知识点六:...
R语言拥有丰富的库和工具,其中ggplot2是用于创建高质量图形的强大包,非常适合数据可视化。 在ggplot2中,创建图形的基本结构是`ggplot(data, aes())`,其中`data`是你使用的数据集,`aes()`定义了图形的美学映射...
通过这份学习笔记,你可以系统地学习和掌握Java编程的核心技术,并逐步提升编写高质量Java程序的能力。同时,不断实践和反思,将理论知识转化为实际编程经验,是成为优秀Java程序员的必经之路。
《高质量C++编程指南》是一本深受欢迎的C++学习资料,特别适合初学者作为入门教程。这本书结合了丰富的编程经验和实例,旨在帮助读者掌握C++编程的核心概念、语法和最佳实践。通过阅读这本书和相应的笔记,学习者...
这份"(强烈推荐大家看一看)高质量C++编程指南(有笔记)1"提供了丰富的资源,旨在帮助学习者提升C++编程技能,特别是在理解和应用方面。下面将详细讨论这份指南中可能涵盖的关键知识点。 1. **基础语法与数据类型**...
【高质量C++复习笔记1】 在C++编程中,理解和运用一些关键概念是至关重要的,这里我们将重点关注断言(Assert)和常量(Const)这两个主题。 ### 断言(Assert) 断言是一种调试工具,它允许程序员在代码中设置...
通过使用泛型,你可以编写一次代码,然后在需要时用不同的数据类型实例化它,提高了代码的复用性和安全性。 3. **委托与事件**:委托是类型安全的函数指针,可以用于实现回调和事件处理。事件则是一种特殊的委托,...
它不仅涵盖了基础语法、高级特性,还深入探讨了如何编写高质量代码的方法与技巧。本书旨在帮助读者掌握优秀的编程实践,并能够在实际项目中应用这些知识,提升软件质量和开发效率。 #### 二、核心知识点概览 #####...
在本节"Go语言学习(五)高质量编程与性能调优实战"中,我们将深入探讨如何利用Go语言的特性编写高效、可靠且可维护的代码,并掌握关键的性能优化技巧。Go语言,作为一种现代化的系统级编程语言,以其并发模型、垃圾...
在这些笔记中,你将首先了解Python3的基本语法,如变量、数据类型(包括整型、浮点型、字符串和布尔型)、输入输出操作以及基本的控制流程(条件语句与循环结构)。这些是编程的基础,让你能够编写简单的程序。 接...
- **作者的初衷与付出**:作者分享了自己两年跨考经历中的艰难与决心,表达了对编写高质量辅导资料的热情和努力,呼吁更多教育工作者投入时间与精力,创作真正有价值的考研辅导书籍。 以上知识点不仅揭示了计算机...
1. **Python基础知识**:学习笔记的前几部分通常会回顾Python的基础,如变量、数据类型(包括整型、浮点型、字符串、布尔型)、运算符、控制流(条件语句、循环结构)、函数定义以及模块导入。这些都是进行数学编程...