我正在写一个类Vec2D
,代表一个二维向量。我将x
和y
存储在double
s。
当被要求生成equals(Object obj
和hashCode()
时,eclipse生成了这个:
@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;
}
Double.doubleToLongBits(x)
在这种情况下有什么意义?我不能简单地写x != other.x
吗?
答案 0 :(得分:12)
简短回答:Eclipse使用Double.doubleToLongBits,因为这是Double.equals的作用:
当且仅当参数不是
true
并且是表示与null
具有相同值的doubl
e的Double对象时,结果为double
由此对象表示。为此,当且仅当方法doubleToLongBits(double)
在应用于每个double
时返回相同的long
值时,才会认为两个0.0==-0.0
值相同。
答案很长:JLS指定了Double.equals和==之间的一些区别。对于JLS 4.2.3和JLS 15.21.1中指定的一个差异:
正零和负零比较相等;因此,表达式
true
的结果为0.0>-0.0
,false
的结果为1.0/0.0
。但其他操作可以区分正负零;例如,1.0/-0.0
的值为正无穷大,而NaN
的值为负无穷大。
另一个方面==
:
如果任一操作数为NaN,则
false
的结果为!=
,但true
的结果为x!=x
。实际上,当且仅当x的值为NaN时,测试
true
为==
。
正如您所看到的,可以将两个double值与equals
进行比较,但实际上对应于在数学和哈希表中使用时的不同行为。因此,在编写生成的相等方法时,Eclipse假设两个双精度只有当且仅当所有可以对它们执行的操作相同时才相等,或者(等效地)如果它们被自动装箱并与它们{{1}进行比较} 方法。如果在double
和Double
之间切换,这一点尤其重要 - 对于不同的等同属性而言,这一点尤为突出。
当然,你可以自由地偏离这个假设:不管这是一个好主意,你可以将特殊情况分配给许多可能的NaN表示中的任何一个,在这种情况下Double.doubleToRawLongBits()
会更好匹配您的equals
和hashCode
方法。出于同样的原因,您的用例可能会将+0.0和-0.0的对象视为等效对象,并保证NaN值不可能,在这种情况下,原始==
比较可能更适合equals
(但在这一点上,模仿hashCode
的相同标准变得困难。)
答案 1 :(得分:3)
由于==
和!=
符合IEEE-754双语,Double.NaN != Double.NaN
和0.0 == -0.0
语义。这些行为可能不是您想要的,因此Double.doubleToLongBits()
将64位double
数据转换为64位long
数据,以便像位移和XOR这样的操作。
老实说,我会说使用doubleToLongBits
是一个错误,因为如果你关心完全相等,你应该使用Double.doubleToRawLongBits()
(它不会对{{}}执行任何翻译取而代之的是{1}}数据。
答案 2 :(得分:0)
快速浏览一下在线javadoc会产生这样的结果:
根据IEEE 754浮点“双格式”位布局返回指定浮点值的表示。
...
在所有情况下,结果都是一个长整数,当给予longBitsToDouble(long)方法时,它将生成一个与doubleToLongBits参数相同的浮点值(除了所有NaN值都折叠为单个“)规范的“NaN值”。
因此,这可能是标准化double
和x
的{{1}}表示的一种方式,因为NaN可以有多个y
表示