Java:比较不同的double和Double

我知道Double是一个包装类,它包含了double数。 今天,我看到了另一个主要区别:

 double a = 1.0; double b = 1.0; Double c = 1.0; Double d = 1.0; System.out.println(a == b); // true System.out.println(c == d); // false 

跟我这么奇怪!!!

所以,如果我们每次使用Double ,我们必须做这样的事情:

 private static final double delta = 0.0001; System.out.println(Math.abs(cd) < delta); 

我无法解释为什么Double直接比较错误。 请解释一下。

谢谢 :)

cd在技​​术上是两个不同的对象,而==运算符只比较引用。

 c.equals(d) 

更好,因为它比较值,而不是参考。 但仍然不理想。 直接比较浮点值应始终考虑一些误差(epsilon)( Math.abs(c - d) < epsilon )。

注意:

 Integer c = 1; Integer d = 1; 

这里比较会产生true ,但这更复杂( Integer内部缓存,在Integer.valueOf() JavaDoc中描述):

此方法将始终缓存-128到127(包括端点)范围内的值,并可以缓存此范围之外的其他值。

为什么valueOf() ? 因为此方法隐式用于实现自动装箱:

 Integer c = Integer.valueOf(1); Integer d = Integer.valueOf(1); 

也可以看看

  • Java中奇怪的整数拳击
  • 如何正确比较Java中的两个整数?

当应用于类类型的表达式时, ==始终执行引用比较( JLS第15.21.3节 )。 所以这一行:

 System.out.println(c == d); 

正在检查cd是否引用相同的对象。 Java中的自动装箱总是(我相信)为floatdouble创建一个新对象(对于整数类型1 ,情况更复杂)。 因此cd引用不同的对象,因此它打印为false

如果要比较对象是否相等,则需要显式调用equals

 System.out.println(c.equals(d)); 

使用double ,它使用数字相等 – 如第15.21.1节所述 。 因此行为上的差异。


1对于整体自动装箱,缓存“小”值 – 因此自动装箱5(比如说)每次都会返回相同的参考值。 “小”的定义是特定于实现的,但它保证在-128到127的范围内。有关详细信息,请参见5.1.7节的底部。

使用equals()检查2个对象的相等性。 ==检查2个引用是否引用内存中的同一对象。

在检查基元类型时,内容检查仅对==可靠。 对于对象类型,最好使用equals方法:

 c.equals(d)