在浏览Guava的源代码时,我遇到了以下代码(内部类hashCode
的{{1}}实现的一部分):
CartesianSet
int adjust = size() - 1;
for (int i = 0; i < axes.size(); i++) {
adjust *= 31;
adjust = ~~adjust;
// in GWT, we have to deal with integer overflow carefully
}
int hash = 1;
for (Set<E> axis : axes) {
hash = 31 * hash + (size() / axis.size() * axis.hashCode());
hash = ~~hash;
}
hash += adjust;
return ~~hash;
和adjust
都是hash
。根据我对Java的了解,int
表示按位否定,因此~
和adjust = ~~adjust
应保持变量不变。运行小测试(当然启用了断言),
hash = ~~hash
证实了这一点。假设Guava家伙知道他们在做什么,他们必须有理由这样做。问题是什么?
编辑正如评论中所指出的,上述测试并未包括for (int i = Integer.MIN_VALUE; i < Integer.MAX_VALUE; i++) {
assert i == ~~i;
}
等于i
的情况。由于Integer.MAX_VALUE
始终为真,我们需要在循环外检查该情况以防止它永远循环。但是,行
i <= Integer.MAX_VALUE
产生编译器警告&#34;比较相同的表达式&#34;,它几乎指出它。
答案 0 :(得分:240)
在Java中,它没有任何意义。
但该评论说该专线专门针对GWT,这是一种将Java编译为JavaScript的方法。
在JavaScript中,整数有点像双打 - 就像整数一样。例如,它们的最大值为2 ^ 53。但bitwise operators将数字视为32位,这正是您在此代码中所需要的。换句话说,~~hash
表示&#34;将hash
视为32位数字&#34;在JavaScript中。具体来说,它会丢弃除最后32位之外的所有位(因为按位~
运算符只查看底部的32位),这与Java溢出的工作方式相同。
如果你没有这个,那么对象的哈希码会有所不同,这取决于它是在Java-land还是在JavaScript中评估(通过GWT编译)。