代碼大全 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]
    收穫滿滿,繼續堅持加油。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章