Java:比较不同的double和Double

Java : different double and Double in comparison

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

1
2
3
4
5
6
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,我们必须这样做:

1
2
private static final double delta = 0.0001;
System.out.println(Math.abs(c-d) < delta);

我不能解释为什么双重比较是错误的。请给我解释一下。

谢谢)


cd在技术上是两个不同的对象,==操作符只比较引用。

1
c.equals(d)

比较值而不是引用时更好。但仍然不理想。直接比较浮点值应始终考虑一些错误(epsilon)(Math.abs(c - d) < epsilon)。

注意:

1
2
Integer c = 1;
Integer d = 1;

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

This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range.

为什么是valueOf()?因为此方法隐式地用于实现自动氧化:

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

也见

  • 爪哇怪诞拳
  • 如何正确地比较Java中的两个整数?


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

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

正在检查cd是否引用相同的对象。Java中的自动装箱(我相信)为EDCOX1、13和EDCOX1 14创建了一个新的对象(对于整数类型来说情况更复杂)。因此,cd是指不同的对象,所以它打印false

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

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

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

1对于整体自动氧化,"小"值被缓存-因此自动氧化5(say)将每次返回相同的引用。"小"的定义是特定于实现的,但它保证在-128到127的范围内。详情见第5.1.7节底部。


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


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

1
c.equals(d)