Java中双波浪线(~~)的含义是什么?

194

当我查看Guava源代码时,我发现了以下一段代码(用于内部类CartesianSethashCode实现的一部分):

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;

adjusthash都是int类型的。根据我对Java的了解,~表示位取反,所以adjust = ~~adjusthash = ~~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;

会产生编译器警告"比较相同的表达式",这基本上已经说明问题了。


42
现在,在项目中包含Guava这个库是相当常见的,我认为劝告远离它的建议是不恰当的。 - yshavit
4
assert 语句没有检查边界情况 Integer.MAX_VALUE。与 -(-Integer.MIN_VALUE) != Integer.MIN_VALUE 相比较。 - Franky
3
@Franky,就像maaartinus所说的那样。-Integer.MIN_VALUE会被转回Integer.MIN_VALUE,所以再次取反只会产生Integer.MIN_VALUE - user743382
2
@maaartinus,@hvd,感谢你们指出这一点。现在我记得-x = (~x) + 1了。 - Franky
7
@dr_andonuts在搞恶作剧吗?为什么要逃避自己不理解的事情。StackOverflow就是为了帮助你学习而存在的。请记住这一点。 - Jared Burrows
显示剩余4条评论
1个回答

246

在Java中,它什么都不表示。

但是这个注释指的是该行代码特别适用于GWT,这是一种将Java编译成JavaScript的方法。

在JavaScript中,整数有点像充当整数的双精度浮点数。例如,它们的最大值为2^53。但是按位运算符会将数字视为32位,这正是您在此代码中所需的。换句话说,在JavaScript中,~~hash表示"将hash视为32位数字"。具体来说,它丢弃除了最低32位之外的所有位(因为按位~操作符只查看最低32位),这与Java的溢出处理方式相同。

如果没有这个,对象的哈希码将因是否在Java领域或JavaScript领域(通过GWT编译)中评估而异。


10
@harold 这不是 GWT 的问题,而是 JavaScript 的问题。这只是该语言中数字工作的方式。 - yshavit
18
@yshavit 然而,这并不是Java中数字的工作方式。如果GWT没有将JS和JVM上数字实现的不同之处对用户进行隐藏,那么它就是一个很差的编译器。 - valderman
8
@harold,是的,JavaScript 在实现整数时存在问题(实际上 JavaScript 中并没有整数类型)。 - Mike G
8
@valderman的观点很好。加上|0~~似乎不难,但我不知道性能损失会有多大(您需要在每个表达式的每个步骤中添加它)。我不知道设计考虑因素是什么。值得一提的是,在GWT的兼容性页面上记录了这种不一致性。 - yshavit
6
hashCode方法很奇怪,因为它刻意地追求,甚至预期会发生溢出。只有在普通的Java整数溢出的情况下才能观察到不一致性,在大多数代码中不会遇到这个问题;它只与这种奇怪的情况相关。 - Louis Wasserman
显示剩余10条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接