问题
I am writing a class Vec2D
, representing a 2 dimensional vector. I store x
and y
in double
s.
When asked to generate equals(Object obj
and hashCode()
, eclipse generated this:
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
long temp;
temp = Double.doubleToLongBits(x);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(y);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Vec2D other = (Vec2D) obj;
if (Double.doubleToLongBits(x) != Double.doubleToLongBits(other.x))
return false;
if (Double.doubleToLongBits(y) != Double.doubleToLongBits(other.y))
return false;
return true;
}
What is the significance of Double.doubleToLongBits(x)
in this context? Can I not simply write x != other.x
?
回答1:
Short answer: Eclipse uses Double.doubleToLongBits because that's what Double.equals does:
The result is
true
if and only if the argument is notnull
and is a Double object that represents adoubl
e that has the same value as thedouble
represented by this object. For this purpose, twodouble
values are considered to be the same if and only if the method doubleToLongBits(double) returns the identicallong
value when applied to each.
Long answer: the JLS specifies a few differences between Double.equals and ==. For one difference specified in JLS 4.2.3 and JLS 15.21.1:
Positive zero and negative zero compare equal; thus the result of the expression
0.0==-0.0
istrue
and the result of0.0>-0.0
isfalse
. But other operations can distinguish positive and negative zero; for example,1.0/0.0
has the value positive infinity, while the value of1.0/-0.0
is negative infinity.
Another regards NaN
:
If either operand is NaN, then the result of
==
isfalse
but the result of!=
istrue
.Indeed, the test
x!=x
istrue
if and only if the value of x is NaN.
As you can see, it's possible for two double values to compare with ==
but actually correspond to different behavior when used in math and hash tables. Thus, when writing a generated equality method, Eclipse makes the assumption that two doubles are only equal if and only if all operations that can be done to them are identical, or (equivalently) if they were autoboxed and compared with their equals
methods. This is particularly important if switching between double
and Double
—it would be particularly unexpected for equality properties to differ there.
Of course, you're free to drift from that assumption: Regardless of whether it's a good idea, you may assign special cases to any of the many possible NaN representations, in which case Double.doubleToRawLongBits()
would be a better match for your equals
and hashCode
methods. By the same token, your use case might treat objects with +0.0 and -0.0 as equivalent and guarantee that NaN values are not possible, in which case a raw ==
comparison may work better for equals
(but at which point emulating the same criteria for hashCode
becomes difficult).
回答2:
Because ==
and !=
follow IEEE-754 semantics for doubles, Double.NaN != Double.NaN
and 0.0 == -0.0
. These behaviors may not be what you want, so Double.doubleToLongBits()
converts the 64 bits of double
data to 64 bits of long
data so that operations like bit shifts and XOR work.
Honestly, though, I would say that the use of doubleToLongBits
is a bug here, since if you care about exact equality you should be using Double.doubleToRawLongBits() (which does not perform any translations on the double
data at all) instead.
回答3:
A quick glance at the online javadoc yields this:
Returns a representation of the specified floating-point value according to the IEEE 754 floating-point "double format" bit layout.
...
In all cases, the result is a long integer that, when given to the longBitsToDouble(long) method, will produce a floating-point value the same as the argument to doubleToLongBits (except all NaN values are collapsed to a single "canonical" NaN value).
So it's probably a way of standardizing the double
representations of x
and y
, as NaN can have multiple double
representations
来源:https://stackoverflow.com/questions/23438530/meaning-of-double-doubletolongbitsx