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

在浏览Guava的源代码时,我遇到了以下代码(内部类实现的一部分):hashCodeCartesianSet

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;

和 都是 s。根据我对Java的了解,意味着按位否定,所以应该保持变量不变。运行小测试(当然,启用断言),adjusthashint~adjust = ~~adjusthash = ~~hash

for (int i = Integer.MIN_VALUE; i < Integer.MAX_VALUE; i++) {
    assert i == ~~i;
}

证实了这一点。假设番石榴家伙知道他们在做什么,那么他们这样做一定有一个理由。问题是什么?

编辑正如注释中指出的那样,上面的测试不包括等于 的情况。由于 始终为 true,因此我们需要在循环外部检查该情况,以防止其永远循环。但是,该行iInteger.MAX_VALUEi <= Integer.MAX_VALUE

assert Integer.MAX_VALUE == ~~Integer.MAX_VALUE;

产生编译器警告“比较相同的表达式”,这几乎钉死了它。


答案 1

在Java中,它没有任何意义。

但该评论说,该行是专门针对GWT的,这是一种将Java编译为JavaScript的方法。

在JavaScript中,整数有点像双精度值作为整数。例如,它们的最大值为 2^53。但是按位运算符将数字视为 32 位,这正是您在此代码中想要的。换句话说,在JavaScript中说“被视为32位数字”。具体来说,它丢弃了除底部32位之外的所有位(因为按位运算符仅查看底部32位),这与Java的溢出工作方式相同。~~hashhash~

如果你没有这个,对象的哈希代码会有所不同,这取决于它是在Java-land还是在JavaScript land(通过GWT编译)中评估的。


答案 2

推荐