Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/395.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/github/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中比较double会得到奇怪的结果_Java_Double_Equals_Autoboxing - Fatal编程技术网

在Java中比较double会得到奇怪的结果

在Java中比较double会得到奇怪的结果,java,double,equals,autoboxing,Java,Double,Equals,Autoboxing,我真的无法理解为什么会发生以下情况: Double d = 0.0; System.out.println(d == 0); // is true System.out.println(d.equals(0)); // is false ?! 但是,这一点与预期的一样有效: Double d = 0.0; System.out.println(d == 0.0); // true System.out.println(d.equals(0.0)); // true 我肯定这在某种程度上与自动

我真的无法理解为什么会发生以下情况:

Double d = 0.0;
System.out.println(d == 0); // is true
System.out.println(d.equals(0)); // is false ?!
但是,这一点与预期的一样有效:

Double d = 0.0;
System.out.println(d == 0.0); // true
System.out.println(d.equals(0.0)); // true
我肯定这在某种程度上与自动装箱有关,但我真的不知道当使用
==
运算符和调用
.equals
时,为什么
0
的装箱方式会不同

这难道不意味着违反了equals合同吗

* It is reflexive: for any non-null reference value * x, x.equals(x) should return * true. *它是自反的:对于任何非空的引用值 *x,x.equals(x)应该返回 *对。 编辑


谢谢你的快速回答。我认为它的装箱方式不同,真正的问题是:为什么它的装箱方式不同?我的意思是,如果
d==0d
d.equals(0d)
更直观,但是如果
d==0
看起来像
Integer
true
d.equals(0)更直观
也应为true。

数字
对象只有在其类型相同时才等于具有相同值的数字。即:

new Double(0).equals(new Integer(0));
new BigInteger("0").equals(new BigDecimal("0"));
类似的组合都是错误的

在您的例子中,文本
0
被装箱到一个
Integer
对象中。

只需将其更改为

System.out.println(d.equals(0d)); // is false ?! now true
您将double与
Integer
0进行比较

在封面下
0
将自动装箱到
Integer
中,Integer的一个实例将被传递到
equals()
方法的
Double
类中,在那里它将进行类似的比较

@Override
    public boolean equals(Object object) {
        return (object == this)
                || (object instanceof Double)
                && (doubleToLongBits(this.value) == doubleToLongBits(((Double) object).value));
    }
当然,它将返回false

更新
当您使用
==
进行比较时,它会比较值,因此不需要自动装箱,它直接对值进行操作。其中
equals()
接受
Object
,因此如果您尝试调用
d1.equals(0)
0
不是Object,因此它将执行自动装箱,并将其打包为作为对象的整数。

d.equals(0)
0
是一个
int
Double.equals()

d == 0
这是向上的

d == 0.0

但是,自动装箱没有向上转换的规则,即使有equals(Object),也不会给出想要双精度而不是整数的命中率。

可能值得注意的是,您应该像这样比较浮点数:

|x - y| < ε, ε very small
| x-y |<ε,ε非常小

或仅仅满足于
d==0
?:)@Simeon在评论中回答了您的问题,当
d
是一个对象而0是基元时,它如何比较值?在它取消装箱
d
(到
int
?或者可能使用
Double.doubleValue()
?)或框0时,我看不出它如何对对象和原语执行
=
。也许我应该问一个单独的问题,因为这个问题有点纠结…它将调用
d.doubleValue()==0
,请在@Simeon中阅读更多关于它的内容:这不是JVM特定的,因为它是由JLS指定的。Jigar Joshi,很抱歉之前的评论,我很困惑;您正在谈论取消装箱转换,但是您应该提到(5.1.8)。
0
是一个
int
,将自动装箱为一个
Integer
@Joachim Sauer,这都是假定的:)但是OP显然不明白。把这些事情说清楚是个好主意。为什么在调用.equals时它会把它框成整数,在调用==时它会把它框成其他的东西?@Simeon因为
equals()
accept
Object
,勾选@Jigar我确实读过你的答案(我甚至投了赞成票),但让我感到奇怪的是,当我们进行
==
比较时,0被装箱到
Double
(或者是吗?!甚至在==比较上发生了什么,应该创建一个对象,以便它可以正确地比较引用?)当我们做
.equals
时,它被装箱为
整数
,所以它实际上根本没有装箱==它的刚转换,这就是我想要的答案。如果正确的值不是0.0,比如0.2323121212,我想你的答案更好。
|x - y| < ε, ε very small