Float.isNaN(float v)方法初探
背景
今天在翻看之前的博客Java容器類淺析二-----HashMap的存取原理,發現了HashMap的全參構造器中有這樣一句代碼
if (loadFactor <= 0 || Float.isNaN(loadFactor))
,當時對這個Float.isNaN(float v)
方法產生了興趣,於是翻看了一下這個方法的源碼,方法體很簡單就一句話:return (v != v);
。
哇,當時就懵逼了! 這是什麼鬼? 自己不等於自己? 怎麼可能! 自己和自己的內存地址居然不一致!
Debug以後發現:原來啊,還真是自己不等於自己!而且還發現了equals()方法的幾個隱藏屬性,收穫滿滿。
溫故而知新,古人誠不我欺!
問題
Float.isNaN(float v)方法
/**
* Returns {@code true} if the specified number is a
* Not-a-Number (NaN) value, {@code false} otherwise.
*
* @param v the value to be tested.
* @return {@code true} if the argument is NaN;
* {@code false} otherwise.
*/
public static boolean isNaN(float v) {
return (v != v);
}
方法很簡單,註釋也是明明白白,沒毛病。
就是這個 v != v
比較令人費解,按照正常的思維,兩個float變量,其 !=
測試肯定是false
;就算是NaN
也得遵守這個規則啊!爲什麼就不對了呢?爲什麼就能在NaN
的時候返回true
呢?
不信邪,debug走起。
驗證
先看圖:
由此圖得出兩個結論:
- NaN是一個Float對象;
- NaN對象的內存地址盡不相同。
擴展
由isNaN(float v)
方法擴展到equals(Object obj)
方法。
看其方法註釋描述:
總結如下:
- 絕大部分情況下,equals方法都相當於比較兩個對象的floatValue;
- 兩個floatValue相等的情況:當且僅當
floatToIntBits(float)
方法返回的位佈局(浮點數二進制存儲方式,詳見Float.floatToIntBits(float value) 是什麼意思?)相等; - 有兩種特殊情況:
- 當Object是一個
NaN
時,equals方法返回true,儘管==
測試返回了false,因爲NaN
的位佈局是固定的0x7fc00000
; - 當兩個浮點數分別爲
+0.0f
和-0.0f
時,equals方法返回false,儘管==
測試返回了true,因爲兩個浮點數的位佈局的符號位不同,而在常量池中爲同一個內存。
- 當Object是一個
同時,由於Float重寫了equals()
方法,所以也重寫了hashCode()
方法,很簡單,直接返回了位佈局。