讀古今文學網 > 編寫高質量代碼:改善Java程序的151個建議 > 建議23:不要讓類型默默轉換 >

建議23:不要讓類型默默轉換

我們出一個小學生的題目給大家做做看,光速是每秒30萬公里,根據光線旅行的時間,計算月亮與地球、太陽與地球之間的距離。代碼如下:


public class Client{

//光速是30萬公里/秒,常量

public static final int LIGHT_SPEED=30*10000*1000;

public static void main(Stringargs){

System.out.println("題目1:月亮光照射到地球需要1秒,計算月亮和地球的距離。");

long dis1=LIGHT_SPEED*1;

System.out.println("月亮與地球的距離是:"+dis1+"米");

System.out.println("--------------------------------------------");

System.out.println("題目2:太陽光照射到地球上需要8分鐘,計算太陽到地球的距離。");

//可能要超出整數範圍,使用long型

long dis2=LIGHT_SPEED*60*8;

System.out.println("太陽與地球的距離是:"+dis2+"米");

}

}


估計你要鄙視了,這種小學生乘法計算有什麼可做的。不錯,確實就是一個乘法運算,我們運行一下看看結果:


題目1:月亮光照射到地球需要1秒,計算月亮和地球的距離。

月亮與地球的距離是:300000000米

--------------------------------------------

題目2:太陽光照射到地球上需要8分鐘,計算太陽到地球的距離。

太陽與地球的距離是:-2028888064米


太陽和地球的距離竟然是負的,詭異。dis2不是已經考慮到int類型可能越界的問題,並使用了long型嗎,為什麼還會出現負值呢?

那是因為Java是先運算然後再進行類型轉換的,具體地說就是因為disc2的三個運算參數都是int類型,三者相乘的結果雖然也是int類型,但是已經超過了int的最大值,所以其值就是負值了(為什麼是負值?因為過界了就會從頭開始),再轉換成long型,結果還是負值。

問題知道了,解決起來也很簡單,只要加個小小的"L"即可,代碼如下:


long dis2=LIGHT_SPEED*60L*8;


60L是一個長整型,乘出來的結果也是一個長整型(此乃Java的基本轉換規則,向數據範圍大的方向轉換,也就是加寬類型),在還沒有超過int類型的範圍時就已經轉換為long型了,徹底解決了越界問題。在實際開發中,更通用的做法是主動聲明式類型轉化(注意不是強制類型轉換),代碼如下:


long dis2=1L*LIGHT_SPEED*60*8;


既然期望的結果是long型,那就讓第一個參與運算的參數也是long型(1L)吧,也就是明說「嗨,我已經是長整型了,你們都跟著我一起轉為長整型吧」。

注意 基本類型轉換時,使用主動聲明方式減少不必要的Bug。