在RegularEnumSet
实现中,有一个代码:
elements = -1L >>> -universe.lengh
它使用 Long 类型整数来实现高效的 EnumSet。
值得注意的是,>>>
的右操作数是一个负数。
我已经测试并发现
int i = -1;
i >>> -3
具有等效的效果
int i = 1;
i << 3;
那么为什么要费心以这种模棱两可的形式写作呢?
摘自"Java 语言规范"第 15.19 节,关于移位 "如果左操作数的提升类型很长,则仅使用右操作数的六个最低阶位作为移位距离。就好像右操作数受按位逻辑 AND 运算符的约束,掩码值0x3f。因此,实际使用的移位距离为 0 到 64,包括 0 到 64。
因此,>>> -3
具有与>>> 61
等效的效果,-1L >>> -n
等于-1L >>> (0x3f&-n)
实际上,这似乎是在长整数的最低n位中生成连续1s
的最有效方法。
首先,请注意,您引用的代码使用 -1L,而不是 -1。长整型是无符号的,因此 -1L 相当于在长整型上设置所有位,或者获得尽可能高的长数。
>>> -3 与 <<3 具有等效的效果
其实不然。无符号右移运算符 (>>>) 将零移入符号位,而 >>
和 <<
保留要移位的值的符号,相应地移位 1 或 0。这就是为什么-1L >>> -3
是7(0111b),1L << 3
是8(1000b)。