了解双重自动装箱
Understanding 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 部分我意识到它没有被指定:
If p is a value of type double, then:
If p is not NaN, boxing conversion converts p into a reference r of
class and type Double, such that r.doubleValue() evaluates to p
Otherwise, boxing conversion converts p into a reference r of class
and type Double such that r.isNaN() evaluates to true
那么,//2
、//4
和 //6
是否会产生未指定的行为,并且可能会根据实施情况得出不同的结果?
除非另有说明,否则所有 JAVA 数字类型都是有符号的
因此,0.0 在二进制中表示为 0000000.......0000000
-0.0 表示为
10000000.......0000000
现在,据我了解,当您使用 equals() 时,比较是从 2 个内存位置逐位完成的,因此在您的情况下会失败。
来自 java.lang.Double 包
Double.equals(Double)
实现如下
public boolean equals(Object obj) {
return (obj instanceof Double)
&& (doubleToLongBits(((Double)obj).value) ==
doubleToLongBits(value));
}
Double equals 方法记录在 API documentation. The double == operation is documented in the Java Language Specification.
对于大多数数字对,它们的结果相同,但它们基于不同的约定。
双 == 与 IEEE 754 算法兼容,其中 NaN 不等于任何东西,甚至不等于它本身,但 0.0 和 -0.0 是相等的。
Double 旨在让 equals 方法与其 compareTo 兼容,反映总顺序,并与其 hashCode 兼容,因此哈希表将与 Double 键一起使用。 NaN 被视为等于自身,-0.0 小于而不等于 0.0.
如果您仔细阅读 Double
的 Javadoc,您会注意到负零和正零不等价,至少在使用 equals()
:
进行比较时是这样的
来自Javadoc:
Note that in most cases, for two instances of class Double, d1 and d2, the value of d1.equals(d2) is true if and only if
d1.doubleValue() == d2.doubleValue()
also has the value true. However, there are two exceptions:
If d1 and d2 both represent Double.NaN, then the equals method returns true, even though Double.NaN==Double.NaN has the value false.
If d1 represents +0.0 while d2 represents -0.0, or vice versa, the equal test has the value false, even though +0.0==-0.0 has the value true.
...for two instances of class Double, d1 and d2, the value of
d1.equals(d2) is true if and only if
d1.doubleValue() == d2.doubleValue()
also has the value true. However, there are two exceptions:
If d1 and d2 both represent Double.NaN, then the equals method returns true, even though Double.NaN==Double.NaN has the value false.
If d1 represents +0.0 while d2 represents -0.0, or vice versa, the equal test has the value false, even though +0.0==-0.0 has the value
true.
This definition allows hash tables to operate properly.
请参考:https://docs.oracle.com/javase/7/docs/api/java/lang/Double.html
Double.equals(Object obj)
的 Javadoc:
Note that in most cases, for two instances of class Double
, d1
and d2
, the value of d1.equals(d2)
is true
if and only if
d1.doubleValue() == d2.doubleValue()
also has the value true
. However, there are two exceptions:
- If
d1
and d2
both represent Double.NaN
, then the equals
method returns true
, even though Double.NaN==Double.NaN
has the value false
.
- If
d1
represents +0.0
while d2
represents -0.0
, or vice versa, the equal
test has the value false
, even though +0.0==-0.0
has the value true
.
This definition allows hash tables to operate properly.
考虑以下示例:
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 部分我意识到它没有被指定:
If p is a value of type double, then:
If p is not NaN, boxing conversion converts p into a reference r of class and type Double, such that r.doubleValue() evaluates to p
Otherwise, boxing conversion converts p into a reference r of class and type Double such that r.isNaN() evaluates to true
那么,//2
、//4
和 //6
是否会产生未指定的行为,并且可能会根据实施情况得出不同的结果?
除非另有说明,否则所有 JAVA 数字类型都是有符号的
因此,0.0 在二进制中表示为 0000000.......0000000
-0.0 表示为 10000000.......0000000
现在,据我了解,当您使用 equals() 时,比较是从 2 个内存位置逐位完成的,因此在您的情况下会失败。
来自 java.lang.Double 包
Double.equals(Double)
实现如下
public boolean equals(Object obj) {
return (obj instanceof Double)
&& (doubleToLongBits(((Double)obj).value) ==
doubleToLongBits(value));
}
Double equals 方法记录在 API documentation. The double == operation is documented in the Java Language Specification.
对于大多数数字对,它们的结果相同,但它们基于不同的约定。
双 == 与 IEEE 754 算法兼容,其中 NaN 不等于任何东西,甚至不等于它本身,但 0.0 和 -0.0 是相等的。
Double 旨在让 equals 方法与其 compareTo 兼容,反映总顺序,并与其 hashCode 兼容,因此哈希表将与 Double 键一起使用。 NaN 被视为等于自身,-0.0 小于而不等于 0.0.
如果您仔细阅读 Double
的 Javadoc,您会注意到负零和正零不等价,至少在使用 equals()
:
来自Javadoc:
Note that in most cases, for two instances of class Double, d1 and d2, the value of d1.equals(d2) is true if and only if
d1.doubleValue() == d2.doubleValue()
also has the value true. However, there are two exceptions:
If d1 and d2 both represent Double.NaN, then the equals method returns true, even though Double.NaN==Double.NaN has the value false. If d1 represents +0.0 while d2 represents -0.0, or vice versa, the equal test has the value false, even though +0.0==-0.0 has the value true.
...for two instances of class Double, d1 and d2, the value of d1.equals(d2) is true if and only if
d1.doubleValue() == d2.doubleValue()
also has the value true. However, there are two exceptions:
If d1 and d2 both represent Double.NaN, then the equals method returns true, even though Double.NaN==Double.NaN has the value false.
If d1 represents +0.0 while d2 represents -0.0, or vice versa, the equal test has the value false, even though +0.0==-0.0 has the value true.
This definition allows hash tables to operate properly.
请参考:https://docs.oracle.com/javase/7/docs/api/java/lang/Double.html
Double.equals(Object obj)
的 Javadoc:
Note that in most cases, for two instances of class
Double
,d1
andd2
, the value ofd1.equals(d2)
istrue
if and only ifd1.doubleValue() == d2.doubleValue()
also has the value
true
. However, there are two exceptions:
- If
d1
andd2
both representDouble.NaN
, then theequals
method returnstrue
, even thoughDouble.NaN==Double.NaN
has the valuefalse
.- If
d1
represents+0.0
whiled2
represents-0.0
, or vice versa, theequal
test has the valuefalse
, even though+0.0==-0.0
has the valuetrue
.This definition allows hash tables to operate properly.