【问题标题】:Difference between double and Double in comparison比较中double和Double之间的区别
【发布时间】:2012-08-26 22:41:09
【问题描述】:

我知道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(c-d) < delta); 

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

【问题讨论】:

  • 使用c.equals(d) 而不是==。 == 只检查引用。
  • @Baz 啊,我明白了。双倍是一类。它将比较对象而不是比较值。当我们使用String 时,这个问题很喜欢。应该使用equals 而不是== :)
  • 另一个区别是 Double 允许 null 值,但 double 不允许。

标签: java double


【解决方案1】:

c 和 d 在技术上是两个不同的对象,== 运算符只比较引用。

c.equals(d)

比较好,因为它比较值,而不是引用。但仍然不理想。直接比较浮点值应始终考虑一些错误 (epsilon) (Math.abs(c - d) &lt; epsilon)。

请注意:

Integer c = 1;
Integer d = 1;

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

此方法将始终缓存 -128 到 127(含)范围内的值,并可能缓存此范围之外的其他值。

为什么是valueOf()?因为这个方法是隐式用来实现自动装箱的:

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

另见

【讨论】:

  • 哦。我已经明白了。当我们使用字符串类时,这个问题很喜欢。但是你的第二个例子很有趣。你能告诉我为什么用整数做它是真的吗:)
  • @hqt:查看我的答案的另见部分中的链接。
  • @hqt 你可以称之为整数池。大小 - 此范围内的所有整数都相等,使用 equals() 和 ==
  • 我想 Jon 记得更清楚 :),所以范围是 -128 到 127(不是我之前写的 -256 -> 255)。总数为 256,正好是 byte 范围。
  • @hqt 尝试一些准备 SCJP / OCPJP 证书的书。你会发现它很快;)或者只是阅读 Effective Java(我认为它也在那里)
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

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

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

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

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

    对于double,它使用数字相等代替 - 正如section 15.21.1 中指定的那样。因此行为上的差异。


    1 对于完整的自动装箱,“小”值被缓存 - 所以自动装箱 5(比如说)每次都会返回相同的引用。 “小”的定义是特定于实现的,但保证在 -128 到 127 的范围内。详见section 5.1.7 底部。

    【讨论】:

    • 关于整数缓存,你能告诉我为什么你能知道这个吗?我在我读过的任何 java 书中都没有看到这些东西。 (而且我认为您并没有学习所有 Java 规范:D)
    • @hqt 即使你不知道所有的规范,但过一段时间你就会知道大部分。这是一个很好的做法,每当你看到一些你不知道它是如何工作的东西时,你就去检查规格和/或来源。新知识使您成为更好的开发人员并降低出现错误的风险。
    【解决方案4】:

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

    c.equals(d)
    

    【讨论】:

      【解决方案5】:

      == 和 equals 之间的区别

      在原始数据类型上使用== 与在对象引用数据类型上使用它不同。

      1. 在原始数据类型上,== 用作equals。
      2. 对于对象引用数据类型== 指的是它们的引用。因此 对象在内存中指向什么。

      考虑案例 1

          double d1 = 10.00;
          double d2 =10.00;
          System.out.println(d1 == d2); 
      

      *输出为 *true

      案例 2:== 引用数据类型

          Double d1 = 10.00;
          Double d2 =10.00;
          System.out.println(d1 == d2);
      

      *输出为 *false

      d1 和 d2 有不同的内存引用。

      要检查此代码的有效性,请考虑以下代码

          Double d1 = 10.00;
          Double d2 = d1;
          System.out.println(d1 == d2);
      

      这将打印true,因为 d1 和 d2 指向相同的内存引用。

      因此

      Java 使用 == 比较 primitives 并检查两个变量是否引用同一个 object

      `等于'

      用于检查两个objects是否等价。

      它还取决于它被调用的对象的实现。对于Strings,equals() 会检查其中的字符。

          Double d1 = 10.00;
          Double d2 = 10.00;
          System.out.println(d1.equals(d2));
      

      打印 true,因为它会查看 d1 和 d2 内部的内容。

      案例1不会编译

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-07
        • 2018-11-30
        • 1970-01-01
        相关资源
        最近更新 更多