在java String source code中,以下评论中注明的地方很少:
// Note: offset or count might be near -1>>>1.
考虑以下示例:
public String(char value[], int offset, int count) {
if (offset < 0) {
throw new StringIndexOutOfBoundsException(offset);
}
if (count < 0) {
throw new StringIndexOutOfBoundsException(count);
}
// Note: offset or count might be near -1>>>1.
if (offset > value.length - count) {
throw new StringIndexOutOfBoundsException(offset + count);
}
this.offset = 0;
this.count = count;
this.value = Arrays.copyOfRange(value, offset, offset+count);
}
我们可以看到,offset
,value.length
和count
都是int
,因此值可能是-1,0,1或任何其他整数。什么是“近”和“&gt;&gt;&gt;”在评论意味着,我在这里错过了一些东西吗?
答案 0 :(得分:20)
值-1>>>1 == 2147483647
是您在Java中可以拥有的最大int
值。
换句话说,-1>>>1 == Integer.MAX_VALUE
。当您使用接近此限制的值进行数学运算时,会增加获得意外结果的机会。例如,int a = (-1>>>1); System.out.println(a < a + 1);
因为整数溢出而打印false
,即使人们可以期望该代码始终打印true
,因为在纯数学中,任何代码都是整数n
确实n < n + 1
。
这段代码的作者只是在解释他(明智的)写作决定
if (offset > value.length - count)
代替相似但不等同的
if (offset + count > value.length)
这最后一个版本可能会导致整数溢出,这对于后面的代码来说可能是一个巨大的麻烦。他警告说,offset
或count
中至少有一个可能是接近Integer.MAX_VALUE
的值,这会增加溢出的可能性。
使用第一个版本(您提到的String源代码中使用的版本),永远不会出现溢出:您确定offset
和count
都是正数或0,因为以前的检查,value.length
也是正数或0,因为数组的长度在Java中总是正数或0,所以不会发生溢出问题!
除了记录选择之外,作者还警告其他开发人员(包括他未来的自我),有一个非常具体的理由要说明这条线的写作方式,以避免任何人试图用它替换它(可能更自然的东西)第二,引入错误的错误版本。
答案 1 :(得分:5)
您可能需要查看Bitwise and Bit Shift Operators有关>>>
运算符的说明:
无符号右移运算符“&gt;&gt;&gt;”将零转换为 最左边的位置
说你有:
int a = -1;
a = a >>> 1;
System.out.println(a);
然后a
将是2147483647(这是Integer.MAX_VALUE
)
<强>为什么吗
由于>>>
运算符填充零并且只有零,无论正数和负数。所以,例如,如果你有:
12 >>> 2
(00000000 00000000 00000000 000011 00&gt;&gt;&gt; 2)然后结果为3.
(即00000000 00000000 00000000 00000011)。
所以,如果你这样做:
System.out.println(Integer.toBinaryString(-1>>>1));
这将打印:
1111111111111111111111111111111
当然,将其转换为十进制,这是2147483647.
正如@BrunoReis(+1)在他的回答中解释的那样,这样做的原因是为了防止可能的整数溢出问题。