Java千問:你真的會用Java的int型變量嗎?有些坑你真的不知道

我們在進行Java編程的時候,使用最頻繁的數據類型基本上就是int型了。平時在使用這種數據類型的過程中,我們似乎也並沒有感覺到有什麼太多需要注意的地方,其實int類型的變量在使用過程中也會有一些隱藏很深的坑,我們通過一篇短文來了解一下。

首先我們先來明確一下Java虛擬機在對int型數據進行處理時默認的兩條規則

1. 當程序出現“整型常量”的時候,默認都是以int型存儲的

2. 如果算術表達式中出現的所有的數字都是int型的,默認運算結果也是int類型

瞭解了這兩條基本規則之後,我們接着往下看。在程序編譯過程中,編譯器只對“直接出現”的int常量進行數據超範圍檢查,而對“運算產生的int型值”並不進行超範圍檢查。這句話是什麼意思呢?我們來看下面的代碼

我們使用數字2200000000給long類型的變量x賦值,2200000000其實並沒有超過long類型數據的範圍,但是編譯器卻認爲這條語句有語法錯誤,爲什麼呢?剛纔我們強調過:當程序出現“整型常量”的時候,默認都是以int型存儲的,這個2200000000就是一個“整型常量”,所以編譯器會把它當作int型數據來看待,儘管它最終被賦值給了long類型的變量。剛纔說過,編譯器會對“直接出現”的int常量進行數據超範圍檢查,這個2200000000就是“直接出現”在程序中的,並且還被當作了int型,所以編譯器要對其進行檢查,經檢查發現這個數字已經超過了int型的表示範圍,所以會報錯。

修改這個錯誤的辦法也很簡單,只要在2200000000後面加一個字母L就可以讓它轉換爲long類型數據,這樣語法錯誤自然消失。那麼,既然編譯器已經已經用如此明顯的形式給我們報錯,我們當然能排除掉錯誤,但是對於編譯器不報錯的情況,我們很有可能就會“掉坑”,來看下面的代碼:

我們希望計算一天有多少微秒(1秒=1百萬微秒),於是我們給出了上面的計算公式,並且考慮到計算結果會超過int類型的表示範圍,我們很小心的把計算結果保存到了一個long類型的變量當中。首先明確,這個計算結果是86400000000,它並沒有超過long類型數據的表示範圍,但是,運行結果如下圖,是一個完全錯誤的數值

這是爲什麼呢?剛纔已經強調過:算術表達式當中,如果全部是int類型的數據進行運算,那麼運行結果也是int類型的。現在程序中的算術表達式就是典型的這種情況:全部由int類型的數據參與運算,所以運算結果也是int類型的。雖然明白了這個道理,但是還是沒說清楚計算結果爲什麼如此“不靠譜”。解釋這個現象,就必須用到我們剛纔所說的一條規則:編譯器對“運算產生的int型值”並不進行超範圍檢查。在運算過程中,因爲全部數據都是int型,所以每一步運算結果都會被保存到一個int型的臨時變量當中。但是因爲每一步的運算結果都不是“直接出現的數字”,所以編譯器對每一步運算結果都不做超範圍檢查,那麼,算着算着,相乘的結果不知不覺就已經超過了int類型的表示範圍,雖然超過了範圍,但編譯器坐視不理,仍然進行賦值。把一個超範圍的數據賦值給int型的臨時變量會導致“溢出”現象,也就是說,運算結果超範圍的高位部分被丟棄了,只保留了低位數據,從而導致產生了一個錯誤結果。所以,我們不能簡單認爲理論上的計算結果86400000000沒有超過long類型數據的表示範圍,就可以直接把這些int型數據直接進行相乘並賦值。消除這個程序錯誤的方法也很簡單,就是把乘法表達式當中任意一個乘數因子的後面加上字母L,使其變成一個long類型的數據就可以了。一旦編譯器發現有long類型的數據參與了運算,就不會把運算結果看作是int型,而是自動提升爲long類型。這樣就不會出錯了。

關於int型數據,還有一個隱藏很深的大坑,大家來看代碼

這個循環看似只能執行101次,其實它是一個無限循環(死循環)!原因就是2147483647是int類型數據所能表示的最大值,而循環變量i在到達最大值以後,再進行加1操作,得到卻是-2147483648!這導致i永遠都會滿足循環條件,從而使看起來有限次數的循環變成了無限。至於爲什麼在int型最大值的基礎上再加1會變成-2147483648,大家可以看《Java千問:Java語言中最大的整數再加1等於多少?》,這裏就不詳細解釋了。

看完這篇文章之後,是不是有一種被驚出一身冷汗的感覺呢?所以千萬不要小看一個簡單的int類型喲!

如果想系統學習Java編程,可以點擊這裏觀看我在本站的視頻課程,如果有問題也可以加入我QQ羣291839907一起討論

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章