Java 中的双波浪号 (~~) 是什么意思?

What is the meaning of double tilde (~~) in Java?

在浏览Guava的源代码时,偶然发现了如下一段代码(hashCode内部classCartesianSet的部分实现):

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 的家伙知道他们在做什么,那么他们这样做肯定是有原因的。问题是什么?

EDIT 正如评论中指出的那样,上面的测试不包括 i 等于 Integer.MAX_VALUE 的情况。由于 i <= Integer.MAX_VALUE 始终为真,我们需要在循环外检查这种情况,以防止它永远循环下去。但是,行

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

产生编译器警告 "Comparing identical expressions",这几乎可以解决问题。

在Java中没有任何意义。

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

在Java脚本中,整数有点像双精度整数。例如,它们的最大值为 2^53。但是 bitwise operators 将数字视为 32 位,这正是您在此代码中想要的。换句话说,~~hash 在 JavaScript 中表示 "treat hash as a 32-bit number"。具体来说,它丢弃除底部 32 位以外的所有位(因为按位 ~ 运算符仅查看底部 32 位),这与 Java 的溢出工作方式相同。

如果你没有那个,对象的散列码会有所不同,这取决于它是在 Java-land 还是在 JavaScript land 中计算(通过 GWT 编译) .