当我查看Guava源代码时,我发现了以下一段代码(用于内部类CartesianSet
的hashCode
实现的一部分):
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
都是int
类型的。根据我对Java的了解,~
表示位取反,所以adjust = ~~adjust
和hash = ~~hash
应该不会改变变量的值。运行小测试(当然要启用断言)后:
for (int i = Integer.MIN_VALUE; i < Integer.MAX_VALUE; i++) {
assert i == ~~i;
}
确认了这一点。假设Guava团队知道他们在做什么,他们肯定有理由这么做。问题是什么呢?
编辑 如评论中所指出的那样,上面的测试未包括i等于Integer.MAX_VALUE
的情况。由于i <= Integer.MAX_VALUE始终为真,我们需要在循环之外检查该情况以防止无限循环。但是,这行代码
assert Integer.MAX_VALUE == ~~Integer.MAX_VALUE;
会产生编译器警告"比较相同的表达式",这基本上已经说明问题了。
assert
语句没有检查边界情况Integer.MAX_VALUE
。与-(-Integer.MIN_VALUE) != Integer.MIN_VALUE
相比较。 - Franky-Integer.MIN_VALUE
会被转回Integer.MIN_VALUE
,所以再次取反只会产生Integer.MIN_VALUE
。 - user743382-x = (~x) + 1
了。 - Franky