摘要:望着小劉愁眉苦臉的眼神 ,煙哥答道:"對,有一個不是數值的值,它就是 NaN ,翻譯過來就是(Not a Number),因此下面的輸出是爲 true。聽小劉說道這裏,煙哥換了一個角度問:"是否存在一個數,滿足 i。

五月的深圳空氣中瀰漫起初夏的味道,淡淡的,暖暖的。春日裏不太張揚的陽光也摻入這股氣息… (煙 哥好文采!)

這天,煙哥愉快的喝着霸氣芝士莓莓莓。一邊東張西望,尋找着可以裝13的機會。一切正如下面這張圖這樣

這時,小劉出現了!沒錯,就是那個大家期待的小劉出現了!她拿着一本《XXXjava筆試指南》來找煙哥。

只見小劉嫺熟的打開這本書,望着整本書滿滿的筆記,煙哥不禁猜測道:"小劉如此熱衷於學習,一定還是單身。"

想到這裏,煙哥不禁更有回答的動力了 (沒

錯,我就是這種人!)

緩存問題

小劉翻到某一頁後,指出下面這樣一道題

public static void main(String[] args){
 Integer a = 50;
 Integer b = 50;
 Integer c = 150;
 Integer d = 150;
 System.out.println(a==b);
 System.out.println(c==d);
}

輸出結果爲

true
false

然後詢問煙哥具體緣由。

煙哥看完以後,內心 正(wei)直(suo) 的笑了笑,心裏想道:"這不是幾年前的老題目了麼,怎麼現在還在考!"

煙哥回答道:"其實很簡單,原理是下面這樣滴!"

JAVA編譯器編譯Integer a = 50的時候,被翻譯成

Integer a = Integer.valueOf(50);

valueOf 的源碼是下面這樣的

看到了嘛,Integer內部有一個 IntegerCache 緩存。對於值範圍在-128到127之間的數,會進行緩存。因此a和b範圍在-128到127之間,所以指向的是同一個對象,所以判斷結果是 true 。而c和d在128之外,所以每次都是返回一個新對象,所以判斷結果是 false

聽到這裏,小劉似乎很滿意的準備打道回府。

"不行,怎麼能這樣讓小劉離開。我得多和小劉說說話!"

於是,煙哥說道:"小劉啊,其實java筆試裏關於數值方面的陷阱,可以玩出很多花樣,你瞭解多少?"

很自然的,小劉的表情是下面這樣的

越界問題

煙哥說道:"這樣吧,先問你一個問題。 Math.abs(Integer.MIN_VALUE)) 的結果是正數還是負數?"

小劉:" Math.abs 是絕對值運算,結果應該是正數吧。"

煙哥:"不對,還是負數。Integer的範圍爲-2147483648~2147483647。不過我們先來看一眼 abs 函數的源碼,如下所示"

public static int abs(int a) {
    return (a < 0) ? -a : a;
}

煙哥:"看了源碼,其實很明顯,絕對值運算的原理是判斷這個數是否大於零,如果小於零則取負值。OK,回到我們題目。"

Integer.MIN_VALUE ,它的十六進制表示是 0x80000000。其符號位爲1,其餘所有的位都是0。取負數(反碼+1)則爲 0x7fffffff+1,也就是 0x80000000。你會發現對 Integer.MIN_VALUE 取負值還是本身。因此,結果還是負數。

小劉:"那你這套理論對 LongShortByte 都成立麼?"

煙哥:"是的,都是成立的,原理都一樣。你可以回去測試一下如下代碼"

Short num =(short)Math.abs(Short.MIN_VALUE));
System.out.println(num);

小劉望着這些代碼,陷入了思考…

突然,小劉回答道:"好像,之前我有看到一個題目是這樣的。是否存在一個數i,可以使其滿足 i+1<i ,這樣看來,這個i就是 Integer.MAX_VALUE ,因爲加完1就溢出了變爲負值了。"

聽小劉說道這裏,煙哥換了一個角度問:"是否存在一個數,滿足 i != 0 && i == -i "

小劉想了下,機智的回答道:"其實還是 Integer.MIN_VALUE ,原因你剛纔說過了!"

唉,沒想到小劉領悟如此的快!

浮點奧祕

煙哥感慨小劉領悟速度的同時,加大難度問道:"是否存在一個數,滿足 i==i+1 ?"

小劉突然懵了,答道:"好像..似乎..應該一個數永遠不會等於自己加一。"

看見小劉懵圈的眼神,煙哥只見自己裝13的目的已經達到,便不再賣關子…

煙哥回答道:"有沒聽過一句話,無窮大加一個常數還是無窮大!所以,下面的例子輸出爲 true "

double i = Double.POSITIVE_INFINITY;
System.out.println(i == i+1);

小劉反懟煙哥,說道:"其實,無窮大減去一個常數也是無窮大。所以下面例子也是輸出爲 true ,而且無窮小也有類似的特性。"

double i = Double.POSITIVE_INFINITY;
System.out.println(i == i-1);

煙哥滿意的點了點頭,感慨小劉成長真快!

突然,靈光一閃,煙哥補充道:"你知不知道有一個數可以滿足 i!=i ?"

小劉再次陷入了深思…嘴裏嘟囔道:"奇怪,還有一個數可以自己不等於自己麼?"

望着小劉愁眉苦臉的眼神 ,煙哥答道:"對,有一個不是數值的值,它就是 NaN ,翻譯過來就是(Not a Number),因此下面的輸出是爲 true !"

double i = Double.NaN;
System.out.println(i != i);

結局

在煙哥一陣裝13後,決定暴露自己的本性。問道:"小劉,你有對象了麼?"

小劉答道:"煙哥,你是個好人,然而我已經有對象了!"

"Boom!"

(本文完!)

相關文章