了解双重自动装箱

时间:2016-03-17 05:21:17

标签: java double autoboxing

考虑以下示例:

public static void main(String[] args) {
    double x1 = 0.0, y1 = -0.0;
    Double a1 = x1, b1 = y1;
    System.out.println(x1 == y1);       //1, true
    System.out.println(a1.equals(b1));  //2, false

    double x2 = 0.0, y2 = 0.0;
    Double a2 = x2, b2 = y2;
    System.out.println(x2 == y2);       //3, true
    System.out.println(a2.equals(b2));  //4, true

    double x3 = 0.0/0.0, y3 = 0.0/0.0;
    Double a3 = x3, b3 = y3;
    System.out.println(x3 != y3);       //5, true
    System.out.println(!a3.equals(b3)); //6, false
}

我试图理解Double的自动装箱,但不能。为什么//2打印false,但//4打印true,而//1//3打印true。为什么他们以不同的方式自动装箱?

咨询以下JLS 5.1.7部分我意识到它没有具体说明:

  

如果p是double类型的值,则:

     
      
  • 如果p不是NaN,则装箱转换将p转换为参考r   class和double类型,使r.doubleValue()求值为p

  •   
  • 否则,装箱转换将p转换为类的引用r   并键入Double,使r.isNaN()计算为true

  •   

那么,//2//4//6是否存在未指明的行为,并且可能会根据实施结果产生不同的结果?

5 个答案:

答案 0 :(得分:3)

除非另有说明,否则所有JAVA数字类型都会被签名

因此,0.0以二进制表示为0000000 ....... 0000000

-0.0表示为 千万........ 0000000

现在,根据我的理解,当你使用equals()时,比较不是从2个内存位置逐位进行的,所以它在你的情况下失败了。

来自java.lang.Double包

Double.equals(Double)实现如下

public boolean equals(Object obj) {
    return (obj instanceof Double)
           && (doubleToLongBits(((Double)obj).value) ==
                  doubleToLongBits(value));
}

答案 1 :(得分:3)

{n}方法记录在API documentation中。双{=>操作记录在Java Language Specification

对于大多数数字对,它们具有相同的结果,但它们基于不同的约定。

double ==与IEEE 754算法兼容,其中NaN不等于任何东西,甚至不等于它本身,但0.0和-0.0相等。

Double被设计为使equals方法与compareTo兼容,反映总顺序,并使用其hashCode,因此哈希表将使用Double键。 NaN被视为等于其自身,-0.0小于,而不是等于0.0。

答案 2 :(得分:2)

如果您仔细阅读Double的Javadoc,您会注意到负零和正零不相等,至少在使用equals()时进行比较:

来自Javadoc

  

请注意,在大多数情况下,对于Double,d1和d2类的两个实例,当且仅当

时,d1.equals(d2)的值为true
d1.doubleValue() == d2.doubleValue()
  

也具有值true。但是,有两个例外:

     

如果d1和d2都表示Double.NaN,则equals方法返回true,即使Double.NaN == Double.NaN的值为false。   如果d1代表+0.0而d2代表-0.0,反之亦然,等值测试的值为false,即使+0.0 == - 0.0的值为true。

答案 3 :(得分:2)

  

...对于Double,d1和d2类的两个实例,其值为   当且仅当

时,d1.equals(d2)为真
d1.doubleValue() == d2.doubleValue() 
     

也具有值true。但是,有两个例外:

     

如果d1和d2都表示Double.NaN,则equals方法返回true,即使Double.NaN == Double.NaN的值为false。

     

如果d1表示+0.0而d2表示-0.0,反之亦然,则等于测试的值为false,即使+0.0 == - 0.0具有该值   真正。

     

此定义允许哈希表正常运行。

请参阅:https://docs.oracle.com/javase/7/docs/api/java/lang/Double.html

答案 4 :(得分:1)

Double.equals(Object obj)的Javadoc:

  

请注意,在大多数情况下,对于Doubled1d2类的两个实例,d1.equals(d2)的值为true当且仅当

d1.doubleValue() == d2.doubleValue() 
     

也具有值true。但是,有两个例外:

     
      
  • 如果d1d2都代表Double.NaN,则equals方法会返回true,即使Double.NaN==Double.NaN的值为false 1}}。
  •   
  • 如果d1代表+0.0d2代表-0.0,反之亦然,则equal测试的值为false ,即使+0.0==-0.0的值为true
  •   
     

此定义允许哈希表正常运行。