代碼如下:
public class Change{
public static void main(String args[]){
final long L1=24* 60 * 60 * 1000 * 1000;
final long L2=24* 60 * 60 * 1000;
System.out.println(L1/L2);
}
}
/**
* output: 5
*/
為什么輸出的是5呢?
再看下面的代碼輸出:
復(fù)制代碼代碼如下:
public class Change{
public static void main(String args[]){
final long L1=24L* 60 * 60 * 1000 * 1000;
final long L2=24L* 60 * 60 * 1000;
System.out.println(L1/L2);
}
}
/**
* output: 1000
*/
這個的輸出才是我們想要的結(jié)果。到底發(fā)生了什么?
這是因為常數(shù)L1的計算“確實”溢出了。盡管計算的結(jié)果適合放入long中,并且其空間還有富余,但這個結(jié)果并不適合放入int中。這個計算完全是以int運算來執(zhí)行的,并且只有在運算完成之后,其結(jié)果才被提升到long,而此時已經(jīng)太遲了:計算已經(jīng)溢出了,它返回的是一個小了200倍的數(shù)值。從int到long是一種拓寬原始類型轉(zhuǎn)換,它保留了(不正確的)數(shù)值。這個值之后被L2整除,而L2的計算是正確的,因為它適合int運算。這樣整除的結(jié)果就得到了5。
那為什么是int運算來執(zhí)行的呢?因為所有乘在一起的因子都是int數(shù)值。當(dāng)你將兩個int數(shù)值相乘時,你將得到另一個int數(shù)值。java不具有目標確定類型的特性,只是一種語言特性,其含義是指存儲結(jié)果的變量的類型會影響到計算所使用的類型。
通過使用long常量來替代int常量作為每一個乘積的第一個因子,就可以很容易的訂正這個程序。
這個教訓(xùn)很簡單:當(dāng)你在操作很大的數(shù)字時,千萬要提防溢出,即使用來保存結(jié)果的變量已顯得足夠大,也并不意味著產(chǎn)生結(jié)果的計算具有正確的類型。當(dāng)你拿不準時,就使用long運算來執(zhí)行整個計算。