建議21:用偶判斷,不用奇判斷
根據奇數判斷奇偶性:i%2==1 ? "奇數":"偶數"
根據偶數判斷奇偶性:i%2==0 ? "偶數":"奇數"
Java中的取餘(%標示符)算法,模擬代碼如下:
//模擬取餘計算,dividend被除數,divisor除數
public static int remainder(int divident, int divisor){
return divident - dividend / divisor * divisor;
}
所以,如果根據奇數判斷奇偶性時,當輸入爲-1時,計算結果爲偶數。
因此,Java在判斷奇偶性的時候要用偶判斷。
建議22:用整數類型處理貨幣
system.out.println(10.00-9.60);
輸出結果是:0.40000000000036
這是因爲在計算機中浮點數有可能(注意有可能)是不準確的,它只是無限接近準確值,而不能完全精確。爲什麼會如此呢?這是由浮點數的存儲規則所決定的,十進制小數是通過“乘2取整,順序排列”法轉換成二進制小數的。
0.4這個不能使用二進制準確的表示,在二進制數世界裏它是一個無限循環的小數,就好比在十進制世界裏沒有辦法準確表示1/3。
解決這種問題有兩個方法:
(1)使用BigDecimal
(2)使用整形(例如先擴大100倍轉變爲整形,然後進行運算,然後再縮小100倍)
建議23:不要讓類型默默轉換
pubic static final LIGHT_SPEED = 30 * 10000 * 1000;
long dis2 = LIGHT_SPEED * 60 * 8;
輸出dis2的結果爲-2028888064
雖然聲明瞭dis2爲long型,但是仍然出現負值是因爲Java是先運算然後進行類型轉換的。所以因爲三個乘數都是int型,三者相乘仍然是int型,但是已經超過int的最大值,所以就變成了負值。
這種問題的解決辦法是將乘數轉換成long型(加一個“L”)
long dis2 = LIGHT_SPEED * 60L * 8;
還沒超過int範圍的時候就已經轉換爲long型,在實際開發中,更通用的做法是主動聲明式類型轉化(注意不是強制類型轉換),代碼如下:
long dis2 = 1L * LIGHT_SPEED * 60 * 8;
基本類型轉換時,使用主動方式減少不必要的Bug。
建議24:邊界,邊界,還是邊界
int cur = 1000;
int limit = 2000;
int order = input.nextInt();
boolean bl = (order+cur)<limit;
其中order爲客戶端輸入的值,當order輸入2147483647時,bl的值爲true。
數字越界使檢驗條件失敗。
建議25:不要讓四捨五入虧了一方
使用BigDecimal類,並且採購setScale方法設置精度。
目前Java支持以下七種舍入方式:
1)ROUND_UP:遠離0方向舍入。(只要捨棄位非0即進位)
2)ROUND_DOWN:趨向0方向舍入。(所有的位都捨棄)
3)ROUND_CEILING:向正無窮方向舍入。(正數類似於ROUND_UP ,負數類似ROUND_DOWN )
4)ROUND_FLOOR:想負無窮方向舍入。(與ROUND_CEILING 相反)
5)HALF_UP:最近數字舍入(5進)(即通常所說的四捨五入)
6)HALF_DOWN:類似HALF_UP,但是5不進位。
7)HALF_EVEN:銀行家算法
銀行家算法規則:
》捨棄位的數值小於5時,直接捨棄;
》捨棄位的數值等於6時,進位後捨去;
》捨棄位的數值等於5時,分兩種情況:5後面還有其他數字(非零),則進位後捨去;若5後面是0(即5是最後一個數字),則根據5前一位數的奇偶性來判斷是否需要進位,技術進位,偶數捨去。
總結成一句話:四捨六入五考慮,五後非零就進一,五後爲零看奇偶,五前爲偶應捨去,五前爲奇要進一。
建議26:提防包裝類型的null值
包裝類型參與運算時,要做null值校驗。
建議27:謹慎包裝類型的大小比較
包裝類型比較大小的時候用compareTo方法進行比較。
==運算符比較的是基本類型是否相等,對於對象則是判斷的兩個對象的引用地址是否相等。
建議28:優先使用整型池
int ii = input.nextInt();
Integer i = new Integer(ii);
Integer j = new Integer(ii);
boolean a = i==j
i=ii;
j=ii;
boolean b = i==j;
i = Integer.valueOf(ii);
j = Integer.valueOf(ii);
boolean c = i==j;
當ii的輸入爲127時,a、b、c的值分別是:false、true、true
當ii的輸入爲128時,a、b、c的值分別是:false、false、false
(1)new產生包裝對象,地址不同,所以不相等。
(2)裝箱動作是通過valueOf方法實現的,也就是說後兩個比較中的算法一樣。
Integer.valueOf的代碼實現:
public static Integer valueOf(int i){
final int offset = 128;
if(i>=-128 && i<=127){ // must cache
return IntegerCache.cache[i + offset];
}
return new Integer(i);
}
說明在裝箱時,如果是-128到127之間的int類型轉換爲Integer對象,則直接從cache數組裏獲得。
cache數組代碼如下:
public static Integer cache[] = new Integer[-(-128) + 127 + 1];
static{
for(int i = 0; i < cache.length; i++){
cache[i] = new Integer(i-128);
}
}
cache是IntegerCache內部類的一個靜態數組,容納的是-128到127之間的Integer對象。通過valueOf產生包裝對象時,若干參數在-128到127之間,則直接從整型池中獲得對象,不在該範圍內的int類型通過new 生成包裝對象。
通過包裝類的valueOf生成包裝實例可以顯著提高空間和時間性能。
建議29:優先選擇基本類型
Java5之後實現了包裝類型與基本類型之間的自動轉換。但無論是從安全性、性能和穩定性方面來說,基本類型都是首選方案。
自動裝箱有一個重要原則:基本類型可以先加寬,在轉變成寬類型的包裝類型,但不能直接轉變成寬類型的包裝類型。
建議30:不要隨便設置隨機種子
Random random = new Random();
for(int i=1;i<4;i++){
System.out.println("第"+i+"次:"+random.nextInt());
}
以上程序中輸出隨機數,三個隨機數都不同,而且運行多次,每次的結果都是不同的。
但如果把random的構造使用隨機數種子的方法:
Random random = new Random(10000);
則每次說出的三個都是同樣的三個隨機數。
此時隨機數的產生取決於種子:
》種子不同,產生的隨機數不同。
》種子相同,即使實例不同也產生相同的隨機數。
Random類的默認種子是System.nanoTime()的返回值(JDK1.5版本以前默認的種子是System.currentTimeMillis()的返回值)
因爲默認的種子是不固定的,所以產生的隨機數也不同。
因此,若非必要,不要設置隨機數種子。
歡迎關注公衆號:
零點小時光
lingdianxiaoshiguang