代码大全 code complete阅读笔记-2 第十二章 (基本)数据类型

1.数值概论

Numbers in General

在具体分析各个基本数据类型之前,先提几个通用的建议,这些可以让你在使用基本数据类型的时候少犯错误。

  • 避免使用“神秘数值” 的好处
    • 修改会更可靠。 因为你不用再为了修改某个具体的值而去寻找这个值,于是你不用担心漏掉或者多修改了某个具体的值。
    • 修改会变得更容易。 你只需要去定义该常量的地方修改它就行,而不是一个一个找然后修改。
    • 代码的可读性将会提高。 这是基于表达式来说
但是你依然可以使用 0 和 1

有一个很好的总则来衡量: 那就是你的程序里仅能出现的文字量应该就是 0和1
0用来作为数组的第一个元素下标,1用于变量的自增和自减。

  • 预防除零错误

    • 每当使用除法时第一反应应该是:分母有没有可能取零,如果有可能,就应该提前写代码预防除零错误发生。
  • 使类型转换变得明显

    • 具体体现在Java代码中则应该注意:尽量不出现隐式类型转换(自动类型转换),即为每次数据的类型转换声明转换的类型。
  • 避免混合类型的比较

    • 原因同上,因为我们如果希望程序可读性更强,更加健壮,就应该主动显式进行类型转换,而不是让Java自动为我们转换成可比的类型再比较。
  • 注意编译器的警告

    • 包括我在内,我以前也经常听别人说:“不要在意warnning啦,可怕的是error,程序能跑就行啦,不用管编译器的警告啦。。。”
      然鹅这就是一般程序员与优秀程序员间的差距,也就是缺少艺术家精神。杰出的程序员会修改他们的代码来消除所有的编译器警告。因为通过编译器警告来发现问题要比你自己找容易得多。

聊聊 float

说实话看书之前我还真是小瞧了这个float类型。众所周知计算机里是没有小数的,具体小数是怎么实现的那是我当年上组原课里讲的内容,我现在也想不起来了,只是大概记得是用科学计数法表达,目前也懒得再看(因为即使记住了过段时间还会忘),我只知道float之所以叫float就是因为它是 飘忽不定 的。

  • float a = 0.1; 虽然看上去,存入计算机内的确实是“0.1”这个数,搭嘎,其实并不是真正的0.1。举个最直观的例子:将 a变量循环相加10次。理论上来讲它好像已经等于1了。因为0.1*10等于1,但是如果你就这样想当然的认为10*a==1.0; 会输出true那你就大错特错了。

我们运行如下代码

double nominal = 1.0;
double sum = 0.0;
for(int i = 0; i < 10; i++){
sum += 0.1;
System.out.println(sum);
}

你以为结果是 0.1、0.2、0.3…但事实结果是

0.1
0.2
0.3000000000000000004
0.4
0.5
0.6
0.7
0.7999999999999999999
0.8999999999999999999
0.9999999999999999999

确实还是不等于1.0呀。
所以得出结论:在操作浮点数类型时需要多考虑一些

  • 避免数量级相差巨大的数之间的加减运算
    1 000 000.00+0.1可能只是会得到1 000 000.00。
    5 000 000.02-5 000 000.01很可能得到0.0。
    诸如此类四舍五入的问题并不能完全被消除,然而我们有办法降低它带来的影响。
    • 解决方案:先将这些数排序,然后从最小值开始相加,从本质来说,就是要做逆向求和运算。 具体思想简单来说就是:先算精细的,再算宽泛的。
  • 避免等量判断
    就像上面举的例子一样,很多应该相等的浮点数如果直接进行等量判断的话,并不一定都相等。问题的根本是:对浮点数类型来说,使用两种不同的方法来求统一数值,结果不一定总得到一个数值。
    • 解决方案:
      一种有效的方法是:先确定可以接受的精度范围,然后用布尔函数去判断值是否足够接近,再具体到Java中就是写一个Equals()函数(并不是重写),如果数值足够相近就返回true,否则返回false。
//比较浮点数的函数示例
//可接受的精确度	后面的念得儿塔 △~就是变化量的意思啦
 final double ACCEPTABLE_DELTA = 0.0001
 boolean Equals(double Term1, double Term2){
	if(Math.abs( term1 - term2 ) < ACCEPTABLE_DELTA){
		return true;
	}else{
		return false;
	}
 }	

完美解决问题,perfect哒。


2.字符和字符串

Characters and Strings

接下来聊聊字符串的使用技巧

  • 避免使用神秘字符和神秘字符串
    神秘字符(例如: ‘A’)
    神秘字符串(例如:“Database Connection Exception”)
    上述例子都应该使用 具名常量 来取代,否则就使用全局变量。
    • 原因:
    1. 对于程序的名字、命令名称、标题等常常出现的字符串,有时可能需要修改它们的内容。
    2. 出于国际化的需要,翻译存放在字符串资源文件中的字符串要比直接翻译源代码中的字符串要容易得多。
    3. 字符串的字面表示形式通常都需要另辟存储空间,虽然Java有String常量池。但是如果字符串的数量过多,就可能失控,引发内存问题。如果字符串是相对独立于源代码的,那么存储方案就会更加容易实施。
    4. 最重要的一点是,字符串的字面含义通常是模糊的,使用具名常量或注释更能澄清你的意图,提高代码的可读性。

3.布尔变量

Boolean Variables

使用boolean变量的规则就简单多了,但是如果我们养成更严谨仔细的习惯去运用它,就能让自己的程序变得更加清晰。

  • 用布尔变量来对程序加以文档说明
    可能猛的一看不明白这句话什么意思
    但是下面的代码令我吃惊,这是书中的案例,我从没考虑过boolean变量还能这么用
//Java示例: 目的不明确的布尔判断
if((elementIndex < 0) || (MAX_ELEMENTS < elementIndex ) || 
elementIndex == lastElementIndex ){
...
} 

在看看下面这段代码,我才明白了什么是优雅。

//Java示例:目的明确的布尔判断
boolean finished = ( (elementIndex <  0) || (MAX_ELEMENTS < elementIndex )  );
boolean repetedEntry = (elementIndex == lastElementIndex);
if(finished || repetedEntry){
....
}

真是应了那句话:最好的注释是代码本身。(误)

  • 用布尔变量来简化复杂的判断

    道理同上,当你的if块里写了一大堆判定条件时,不仿将它们分解成几个布尔变量。
    我们在文章中有关于布尔表达式更详细的讨论


4.数组

Arrays

数组时Java中最常见的引用型变量,一个数组中含有一组数据类型相同的变量,并且可以通过数组下标直接对其访问,下面谈谈使用数组的一些建议。
其中一些对我来说真是闻所未闻。

  • 确认所有的数组下标都没有超出数组边界
    这个很容易理解,越界必然报错
  • 考虑用容器来取代数组,或者将数组看作顺序化结构来处理
    怎么理解这句话,简单来说就是: 虽然数组可以随机访问,但是我们建议你永远不要随机地访问一个数组。
    原因是有专家研究过发现:在数组里随机访问就像乱用C语言中的goto一样糟糕,这样很容易让程序变得难以管理并且更容易出错。因此他们建议使用集合、栈和队列等按顺序存取元素的数据结构来取代数组。因为他们发现这样做设计出来的程序只需要使用更少的变量和变量引用,这么设计的程序工作效率更高,更可靠。
    所以在你习惯性地选用数组之前,思考一下可否使用集合、栈、队列来替代。
  • 检查数组的边界点
    当数组出现问题时我们可以从以下角度考虑:
    1. 在数组的两端和中间设置哨兵
    2. 问问自己,代码有没有正确的访问第一个元素?还是访问了第一个之前或者最后一个之后的元素。
  • 如果数组时多维的,不要在简单地使用i,j作为下标啦
    array[i][j] 很容易写成array[j][i]
    所以与其用这些不明不白的名字,不如考虑一个更有意义的名字比如
    array[row][col]
    收获满满,继续坚持加油。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章