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

Почему равный оператор работает для значения Integer до 128 числа?

Почему Integer "=" оператор не работает для 128 и после значений Integer? Может ли кто-нибудь объяснить эту ситуацию?

Это моя среда Java: java version "1.6.0_37"

Java (TM) SE Runtime Environment (сборка 1.6.0_37-b06)

Java HotSpot (TM) 64-разрядная серверная VM (сборка 20.12-b01, смешанный режим)

Пример кода:

    Integer a;
    Integer b;
    a = 129;
    b = 129;

    for (int i = 0; i < 200; i++) {
        a = i;
        b = i;

        if (a != b) {
            System.out.println("Value:"+ i + " - Different values");
        } else {
            System.out.println("Value"+ i + " Same values");
        }
    }

Некоторая часть вывода консоли:

Value:124 - Same values
Value:125 - Same values
Value:126 - Same values
Value:127 - Same values
Value:128 - Different values
Value:129 - Different values
Value:130 - Different values
Value:131 - Different values
Value:132 - Different values

Спасибо!

4b9b3361

Ответ 1

Проверьте исходный код Integer. Вы можете увидеть кеширование значений там.

Кэширование происходит только в том случае, если вы используете Integer.valueOf(int), а не при использовании new Integer(int). Используемый вами автобоксинг использует Integer.valueOf

В соответствии с JLS вы всегда можете рассчитывать на то, что для значений от -128 до 127 вы получаете идентичные объекты Integer после autoboxing и на некоторых реализациях вы можете получить одинаковые объекты даже для более высоких значений.

Фактически в Java 7 (и я думаю, что в более новых версиях Java 6), реализация класса IntegerCache изменилась, а верхняя граница больше не жестко закодирована, но он настраивается через свойство "java.lang.Integer.IntegerCache.high", поэтому, если вы запустите свою программу с параметром VM -Djava.lang.Integer.IntegerCache.high=1000, вы получите "Те же значения" для всех значений.

Но JLS все еще гарантирует это только до 127:

В идеале, бокс данного примитивного значения p всегда будет давать идентичную ссылку. На практике это может оказаться невозможным с использованием существующих методов внедрения. Правила выше - прагматичный компромисс. Последнее заключительное предложение требует, чтобы определенные общие значения всегда помещались в неразличимые объекты. Реализация может кэшировать эти, лениво или нетерпеливо.

Для других значений эта формулировка запрещает любые предположения о идентичности вложенных значений в части программиста. Это позволило бы (но не требовать) совместного использования некоторых или всех этих ссылок.

Это гарантирует, что в большинстве распространенных случаев поведение будет желательным, не налагая чрезмерного штрафа за производительность, особенно на небольшие устройства. Меньшие реализации, ограниченные памятью, могут, например, кэшировать все символы и шорты, а также целые и длинные строки в диапазоне от -32K до + 32K.

Ответ 2

В соответствии со спецификациями Java Language:

Если значение p в коробке равно true, false, байт, a char в диапазоне \ u0000 to\u007f, или int или short number между -128 и 127, затем пусть r1 и r2 - результаты любых двух бокс-преобразований p. это всегда случай, когда r1 == r2.

JLS Boxing Conversions

Обратитесь к этой статье за ​​дополнительной информацией о int-кешировании

Ответ 3

Integer - это класс-оболочка для int.

Integer != Integer сравнивает фактическую ссылку на объект, где int != int будет сравнивать значения.

Как уже указывалось, значения -128 - 127 кэшируются, поэтому для них возвращаются те же объекты.

Если вне этого диапазона будут созданы отдельные объекты, поэтому ссылка будет отличаться.

Чтобы исправить это:

  • Сделайте типы int или
  • Перечислите типы int или
  • Используйте .equals()

Ответ 4

Объект Integer имеет внутренний механизм кэширования:

private static class IntegerCache {
    static final int high;
    static final Integer cache[];

    static {
        final int low = -128;

        // high value may be configured by property
        int h = 127;
        if (integerCacheHighPropValue != null) {
            // Use Long.decode here to avoid invoking methods that
            // require Integer autoboxing cache to be initialized
            int i = Long.decode(integerCacheHighPropValue).intValue();
            i = Math.max(i, 127);
            // Maximum array size is Integer.MAX_VALUE
            h = Math.min(i, Integer.MAX_VALUE - -low);
        }
        high = h;

        cache = new Integer[(high - low) + 1];
        int j = low;
        for(int k = 0; k < cache.length; k++)
            cache[k] = new Integer(j++);
    }

    private IntegerCache() {}
}

Также см. метод valueOf:

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

Вот почему вы должны использовать valueOf вместо new Integer. Autoboxing использует этот кеш.

Также см. этот пост: https://effective-java.com/2010/01/java-performance-tuning-with-maximizing-integer-valueofint/

Использование == не является хорошей идеей, используйте equals для сравнения значений.

Ответ 5

Используйте .equals() вместо ==.

Целочисленные значения кэшируются только для чисел от -127 до 128, потому что они используются чаще всего.

if (a.equals(b)) { ... }

Ответ 6

В зависимости от того, как вы получаете экземпляры Integer, он может не работать для какого-либо значения:

System.out.println(new Integer(1) == new Integer(1));

печатает

false

Это связано с тем, что оператор ==, применяемый к операндам с типизированным типом, не имеет ничего общего со значением, которое представляют эти операнды.

Ответ 7

Это потому, что логика реализации класса Integer. Он подготовил объекты для чисел до 128. Вы можете проверить http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/Integer.java источник open-jdk, например (поиск в кеше []). < бр /" > В принципе, объекты не следует сравнивать с помощью == вообще, за одним исключением из Enums.