Подтвердить что ты не робот

"смещение или подсчет могут быть около -1 >>> 1". Что это значит

В java String исходный код, отмечено несколько мест со следующим комментарием:

// 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, либо любые другие целые числа. Что означает "рядом" и " → > " в комментарии, я что-то упустил?

4b9b3361

Ответ 1

Значение -1>>>1 == 2147483647 - это максимальное значение int, которое вы можете иметь в Java.

Иными словами, -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, потому что длина массива всегда положительна или 0 в Java, поэтому проблемы с переполнением не могут произойти!

В дополнение к документированию выбора автор предупреждает других разработчиков (в том числе о его будущей "я" ), что существует очень конкретная причина для того, чтобы эта строка была написана так, как она есть, чтобы избежать того, кто соблазн заменить ее на возможно, более естественным образом), во-вторых, неправильная версия от введения ошибки.

Ответ 2

Вы можете посмотреть Побитовые и операторы сдвига бит для объяснения оператора >>>:

Беззнаковый оператор сдвига вправо " → > " сдвигает нуль в крайняя левая позиция

Скажите, что у вас есть:

int a = -1;
a = a >>> 1;
System.out.println(a);

Тогда a будет 2147483647 (что есть Integer.MAX_VALUE)

Почему?

Так как оператор >>> заполняет нули и только нули независимо от положительного и отрицательного числа. Так, например, если у вас есть:

12 >>> 2

(00000000 00000000 00000000 000011 00 → > 2), тогда результат равен 3.

(который является 00000000 00000000 00000000 00000011).

Итак, если вы сделаете:

System.out.println(Integer.toBinaryString(-1>>>1));

Это напечатает:

1111111111111111111111111111111

И, конечно, преобразование его в десятичное, это 2147483647.

Как пояснил @BrunoReis (+1) в своем ответе, причина для этого - предотвратить возможные проблемы с переполнением целых чисел.