“偏移或计数可能接近-1>>> 1.”这是什么意思

时间:2013-04-17 07:41:12

标签: java

在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);
}

我们可以看到,offsetvalue.lengthcount都是int,因此值可能是-1,0,1或任何其他整数。什么是“近”和“&gt;&gt;&gt;”在评论意味着,我在这里错过了一些东西吗?

2 个答案:

答案 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)

这最后一个版本可能会导致整数溢出,这对于后面的代码来说可能是一个巨大的麻烦。他警告说,offsetcount中至少有一个可能是接近Integer.MAX_VALUE的值,这会增加溢出的可能性。

使用第一个版本(您提到的String源代码中使用的版本),永远不会出现溢出:您确定offsetcount都是正数或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)在他的回答中解释的那样,这样做的原因是为了防止可能的整数溢出问题。