Результаты сравнения целых чисел различаются в Java

Я начинающий Java-программист и столкнулся с очень странным сценарием, как показано ниже.

public static void main(String[] args) {
    Integer a = 500;
    Integer b = 500;

    // Comparing the values.
    a <= b; // true
    a >= b; // true
    a == b; // false

    // Reassigning the values
    a = 50;
    b = 50;

    // Again comparing the values.
    a <= b; // true
    a >= b; // true
    a == b; // true
}

Мой вопрос: почему результаты a == b различаются в зависимости от значений?


person user3374518    schedule 04.03.2014    source источник
comment
Это очень классический вариант: маленькие целые числа кэшируются.   -  person Denys Séguret    schedule 04.03.2014
comment
a.equals(b) будет true.   -  person Maroun    schedule 04.03.2014


Ответы (3)


Ответ на этот вопрос лежит в пределах понимания Автоупаковка, заданная языком программирования Java.

Разница в результатах a == b возникает из-за того, что любое целое число от -128 до 127 кэшируется классом Integer. Когда создается int в пределах этого диапазона, он извлекается из IntegerCache, а не создает новый целочисленный объект.

Это ошибка? Конечно, нет!

Класс Java Integer также называется классом оболочки, потому что он предоставляет объект, который является оболочкой примитивного типа данных int. В Java сравнение двух объектов-значений не является прямым. Мы должны переопределить метод Object.equal (а также Object.hashCode) и использовать его для определения равенства двух объектов. Используя оператор ==, в этом случае мы сравниваем адреса двух физических объектов. Java требует, чтобы новый оператор создавал объекты, которые будут храниться в куче JVM. Локальные переменные хранятся в стеке JVM, но они содержат ссылку на объект, а не на сам объект.

В первом случае, когда мы проверяем a == b, мы фактически проверяем, указывают ли обе ссылки на одно и то же место. Ответ на это НЕТ!

Но что происходит, когда a и b равны 50? Чтобы ответить на этот вопрос, мы должны взглянуть на приведенный ниже метод Integer.valueOf.

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

Мы используем Autoboxing функцию Java через этот Integer.valueOf метод для сравнения a == b. С целью оптимизации использования ресурсов класс Integer поддерживает кэш-память из Integer экземпляров. Таким образом, все новые целочисленные запросы со значением от -128 до IntegerCache.high (настраиваемое) будут возвращать идентичный объект, выделенный один раз. Итак, когда мы спрашиваем, равно ли a == b, мы получаем истину, потому что за сценой a и b указывают на одну и ту же ячейку памяти.

Теперь возникает еще один вопрос: Приводит ли этот подход к проблемам с совместным использованием экземпляров? К счастью, ответ нет, потому что Integer был определен как неизменяемый объект и это означает, что если вы хотите изменить его, вам нужно получить новый экземпляр… захватывающе, не правда ли?

Шишир

person Shishir Kumar    schedule 04.03.2014
comment
@Downvoter, можете ли вы объяснить причину понижения голоса? - person Shishir Kumar; 04.03.2014
comment
Не понижатель, но если вы на самом деле не отвечаете на вопрос, предоставляя объяснение SO, это, вероятно, следует сделать в комментарии, а не в ответе. - person Michelle; 04.03.2014
comment
@Michelle: обновил ответ с объяснением :) - person Shishir Kumar; 04.03.2014

Да . Потому что значения из диапазона от -127 до 128 будут храниться в кеше. поэтому используйте равные и сравните.

person muthukumar    schedule 04.03.2014

Java интернировала значения от -128 до 127.

Вот почему вы получаете true при сравнении двух объектов Integer в этом диапазоне с ==.

person Konstantin Yovkov    schedule 04.03.2014