Float.isNaN(float v)方法初探

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走起。

验证

先看图:
Float.isNaN(float v)方法初探_第1张图片
由此图得出两个结论:

  • NaN是一个Float对象;
  • NaN对象的内存地址尽不相同。

扩展

isNaN(float v)方法扩展到equals(Object obj)方法。
看其方法注释描述:
Float.isNaN(float v)方法初探_第2张图片

总结如下:

  • 绝大部分情况下,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()方法,很简单,直接返回了位布局。

你可能感兴趣的:(JAVA相关笔记,源码分析)