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


192

浏览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;

两者的adjusthashint秒。根据我对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;

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


42
这些天来,@dr_andonuts Guava是一个非常标准的库,要包含在项目中-我认为建议不要太远。
yshavit 2015年

4
断言不检查边缘情况Integer.MAX_VALUE。与对比-(-Integer.MIN_VALUE) != Integer.MIN_VALUE
Franky

3
@Franky maaartinus说了什么。-Integer.MIN_VALUE环绕到Integer.MIN_VALUE,因此再次否定就可以再次产生Integer.MIN_VALUE

2
@ maaartinus,@ hvd,感谢您指出这一点。现在我记得了-x = (~x) + 1
Franky

7
@dr_andonuts拖钓?为什么要逃避您不了解的事情。这就是StackOverflow的目的:帮助您学习。
Jared Burrows 2015年

Answers:


245

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

但是那条评论说这条线是专门针对GWT的,这是将Java编译为JavaScript的一种方式。

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

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


10
@harold不是GWT,而是JavaScript。只是现在数字以这种语言工作。
yshavit 2015年

18
@yshavit但是,这不是数字在Java中的工作方式。如果GWT不能掩盖用户在JS和JVM上实现数字方式不同的事实,那么它确实是一个糟糕的编译器。
valderman

8
@harold,是的,这是JavaScript错误地实现了整数(JavaScript中实际上没有诸如整数类型之类的东西)。
MikeTheLiar 2015年

8
@valderman很好。添加|0or ~~听起来并不困难,尽管我不知道性能会受到什么影响(您必须在每个表达式的每个步骤都添加它)。我不知道设计注意事项是什么。首先,不一致之处记录在GWT的兼容性页面上
yshavit 2015年

6
hashCode之所以怪异,是因为它故意使甚至希望发生溢出。唯一可以观察到不一致的地方是普通的Java int溢出的地方,这不是大多数代码中都会出现的问题。这只是在这个奇怪的情况下相关。
Louis Wasserman
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.