小编典典

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

all

在浏览 Guava 的源代码时,我遇到了以下一段代码(hashCode内部类的部分实现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和都是s hashint根据我对 Java 的了解,~这意味着按位否定,因此adjust = ~~adjust应该hash = ~~hash保持变量不变。运行小测试(当然,启用断言),

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

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

编辑 正如评论中指出的那样,上面的测试不包括iequals的情况Integer.MAX_VALUE。由于i <= Integer.MAX_VALUE总是正确的,我们需要在循环外检查这种情况,以防止它永远循环。然而,线

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

产生编译器警告“比较相同的表达式”,这几乎可以说明问题。


阅读 156

收藏
2022-07-16

共1个答案

小编典典

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

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

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

如果你没有,对象的哈希码会有所不同,具体取决于它是在 Java 领域还是在 JavaScript 领域(通过 GWT 编译)进行评估。

2022-07-16