In java String source code, there are few places noted with the following comment:
// Note: offset or count might be near -1>>>1.
Consider the following example:
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);
}
As we can see, offset
, value.length
and count
are all int
, thus the value might be either -1, 0, 1, or any other integers. What does the "near" and ">>>" in the comment means, am I missing something here?
The value -1>>>1 == 2147483647
is the maximum int
value you can have in Java.
In other words, -1>>>1 == Integer.MAX_VALUE
. When you do maths with values close to such limits, you increase your chances of getting unexpected results. For instance, int a = (-1>>>1); System.out.println(a < a + 1);
prints false
because of an integer overflow, even though one could expect that code to always print true
since, in pure maths, for any integer n
it is true that n < n + 1
.
The author of that piece of code is just explaining his (wise) decision to write
if (offset > value.length - count)
instead of the similar-looking-but-not-equivalent
if (offset + count > value.length)
This last version could cause an integer overflow, which could be a huge trouble for the code that follows. He is alerting to the fact that there's a possibility that at least one of offset
or count
could be a value close to Integer.MAX_VALUE
, which increases the possibility of the overflow.
With the first version (the one used in the source code for String you mention), there can never be an overflow: you know for sure that both offset
and count
are positive or 0 because of previous checks, and value.length
is also positive or 0 because the length of an array is always positive or 0 in Java, so no overflow problems can happen!
In addition to documenting the choice, the author warns other developers (including his future self) that there's a very specific reason for that line to be written the way it is, to avoid anyone who is tempted to replace it with the (possibly more natural looking) second, incorrect version from introducing a bug.
You might want to look at Bitwise and Bit Shift Operators for explanation about the >>>
operator:
The unsigned right shift operator ">>>" shifts a zero into the leftmost position
Say you have:
int a = -1;
a = a >>> 1;
System.out.println(a);
Then a
will be 2147483647 (Which is Integer.MAX_VALUE
)
Why?
Since the >>>
operator fills zeros and only zeros no matter positive and negative number. So, for example, if you have:
12 >>> 2
(00000000 00000000 00000000 000011 00 >>> 2) then the result is 3.
(Which is 00000000 00000000 00000000 00000011).
So, if you'll do:
System.out.println(Integer.toBinaryString(-1>>>1));
This will print:
1111111111111111111111111111111
And of course, converting it to decimal, this is 2147483647.
As @BrunoReis (+1) explained in his answer, the reason for doing this is to prevent possible integer overflow problems.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With