Java中的double tilde(~~)是什么意思?

Hal*_*ast 192 java gwt bit-manipulation bitwise-operators

在浏览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;
Run Code Online (Sandbox Code Playgroud)

两者的adjusthashint秒.从我所知道的关于Java,~意味着位求反,所以adjust = ~~adjusthash = ~~hash应离开变量不变.运行小测试(当然启用断言),

for (int i = Integer.MIN_VALUE; i < Integer.MAX_VALUE; i++) {
    assert i == ~~i;
}
Run Code Online (Sandbox Code Playgroud)

证实了这一点.假设Guava家伙知道他们在做什么,他们必须有理由这样做.问题是什么?

编辑正如评论中指出的,上述测试不包括i等于的情况Integer.MAX_VALUE.由于i <= Integer.MAX_VALUE总是如此,我们需要在循环外检查这种情况,以防止它永远循环.但是,行

assert Integer.MAX_VALUE == ~~Integer.MAX_VALUE;
Run Code Online (Sandbox Code Playgroud)

产生编译器警告"比较相同的表达式",它几乎指出了它.

ysh*_*vit 244

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

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

在JavaScript中,整数有点像双打 - 即整数.例如,它们的最大值为2 ^ 53.但是按位运算符将数字视为32位,这正是您在此代码中所需的.换句话说,在JavaScript中~~hash说" hash视为32位数".具体来说,它会丢弃除最后32位之外的所有位(因为按位运算~符仅查看底部的32位),这与Java的溢出工作方式相同.

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

  • @yshavit然而,它不是*数字如何在Java中工作.如果GWT没有隐藏数字在JS中以及在用户的JVM上实现不同的事实,那么它确实是一个糟糕的编译器. (18认同)
  • @harold这不是一个GWT的东西,它是一个JavaScript的东西.那就是现在用这种语言编号. (10认同)
  • @harold,是的,它是错误地实现整数的JavaScript(在JavaScript中实际上没有整数类型). (8认同)
  • @valderman这是一个好点.添加"| 0"或"~~"听起来并不难,但我不知道性能的影响是什么(你必须在每个表达式的每一步添加它).我不知道设计考虑因素是什么.Fwiw,不一致性记录在[GWT兼容性页面](http://www.gwtproject.org/doc/latest/DevGuideCodingBasicsCompatibility.html)上. (8认同)
  • `hashCode`是奇怪的,因为它_deliberately_ court,甚至期望溢出发生.您可以观察到不一致的唯一地方是普通Java int会溢出的地方,这不是大多数代码中出现的问题; 它与这个奇怪的案例有关. (6认同)
  • 通常是`| 0`(或零)用于获得相同的东西(http://stackoverflow.com/questions/7487977/using-bitwise-or-0-to-floor-a-number) (5认同)
  • 这是有道理的.似乎JIT编译器也会优化这些语句:当我运行上面的"测试"时,它退出的速度很快,似乎整个循环被删除为死代码. (2认同)
  • @valderman:至关重要的是,它不是*Java编译器,也不是在电视上播放.它是一种像Java一样(好吧,很多)的语言的编译器. (2认同)