Float.isNaN(float v)方法初探

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,因爲兩個浮點數的位佈局的符號位不同,而在常量池中爲同一個內存。

同時,由於Float重寫了equals()方法,所以也重寫了hashCode()方法,很簡單,直接返回了位佈局。

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