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

Почему assert используется в методе Integer.valueOf для класса Integer?

Я вникал в то, как класс Integer фактически использует кешированные объекты, и я нашел код ниже в методе Integer.valueOf:

public static Integer valueOf(int i) {
    assert IntegerCache.high >= 127;
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

Мой вопрос:

4b9b3361

Ответ 1

Цель утверждений - установить инварианты и документировать реализацию. Здесь это подтверждается тем фактом, что при вводе метода valueOf значение IntegerCache.high гарантировано не менее 127. Лучше написать утверждение вместо комментария, потому что assert также будет проверяться JVM, когда активна соответствующая опция командной строки (-esa).

Обычно это утверждение никогда не будет бросать, потому что IntegerCache.high инициализируется следующим образом:

int h = 127;
String integerCacheHighPropValue =
            sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
    try {
        int i = parseInt(integerCacheHighPropValue);
        i = Math.max(i, 127);
        // Maximum array size is Integer.MAX_VALUE
        h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
    } catch( NumberFormatException nfe) {
        // If the property cannot be parsed into an int, ignore it.
    }
}
high = h;

Этот код гарантирует, что значение будет не менее 127. Таким образом, утверждение может вызывать, если вы изменяете IntegerCache.high (используя отражение и setAccessible(true)) или если JDK будет изменен в будущем, и ошибка будет введена в IntegerCache.high код инициализации. Вот почему существуют утверждения: ловить ошибки.

Ответ 2

JLS обязывает, чтобы целочисленный кеш находился на месте для целых чисел от -128 до 127.

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

Тем не менее, он никогда не может быть меньше 127, иначе реализация больше не будет соответствовать JLS - и это будет довольно большой сделкой, поэтому (я считаю), почему существует утверждение assert!

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

Также обратите внимание, что оператор assert будет пропущен, если он не работает с -ea, поэтому при нормальном использовании для этой проверки нет накладных расходов времени.

Ответ 3

Кэш, обычно для -128... 127, может быть увеличен, что может быть причиной: он не должен уменьшаться. И поскольку код будет работать даже без кеша, утверждение может быть мягким: рассказывать о дефекте производительности при разработке. Поскольку утверждения не влияют на производственный код.

Ответ 4

Глядя на

http://www.docjar.com/html/api/java/lang/Integer.java.html

Я вижу этот комментарий

       /*
        * WARNING: This method may be invoked early during VM initialization
        * before IntegerCache is initialized. Care must be taken to not use
       * the valueOf method.
       */

Если они использовали valueOf в parseInt, тогда, когда parseInt вызывается в начале инициализации VM, значение high будет фактически равно нулю.

Я не уверен, какие проблемы могут возникнуть, но, по-видимому, кто-то думал, что это стоит того, чтобы защитить.

  • что такое использование assert IntegerCache.high >= 127; Я читал, что assert обеспечивает эффективный способ обнаружения и исправления ошибок программирования. Но это код времени выполнения, почему кто-то будет использовать assert?

Защита от кода, вызываемого во время инициализации VM, вызывающего метод valueOf.

  1. И когда в этом сценарии будет выбрано AssertionError?

Если вы запускаете java с параметром -ea (разрешаете утверждения), и есть некоторый код инициализации, который вызывает valueOf, JVM почти сразу же сбой из-за AssertionError. Надеюсь, команда Java проверит этот материал и исправит код нарушения, прежде чем выпустить его в дикую природу.

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