Проблема.

В чем проблема в указанной выше программе?

В приведенной выше задаче первое утверждение печатает true, а второе — false.

Когда a1,a2 содержат одно и то же значение, а b1,b2 содержат одно и то же значение, тогда почему только a1==a2 истинно, а b1==b2 ложно;

Давайте разберемся, почему Java показывает такое странное поведение. Во-первых, давайте разберемся, что такое автобокс.

Автобокс

Всякий раз, когда мы присваиваем примитивное значение int ссылочному типу Integer, например, b1=1000: java создает* (или возвращает из кеша) объект Integer со значением 1000 и присваивает его ссылочной переменной (b1).

Это автоматическое преобразование примитивного типа int в целочисленный объект называется автоупаковкой в ​​java.

Причина, по которой a1==a2 возвращает true, а b1==b2 возвращает false, заключается в том, что java кэширует объекты Integer в диапазоне [-128,127] включительно.

Поэтому всякий раз, когда мы создаем целочисленный объект со значением в диапазоне [-128,127], java возвращает экземпляр объекта из кеша. Из-за этого a1 и a2 указывают на один и тот же целочисленный объект со значением 100 в кеше, поэтому a1==a2 возвращает true. Но для b1 и b2 создаются новые объекты, поэтому b1 и b2 указывают на разные объекты, поэтому b1==b2 возвращает false.

Кэширование применяется только тогда, когда мы получаем объект Integer с помощью метода Integer.parseInt(i) или метода Integer.valueOf(i). (метод valueOf(i) внутренне вызывает метод parseInt(i)).

Если мы явно создадим два объекта Integer с одним и тем же значением (используя оператор new), то никакие кэшированные объекты не возвращаются, и для каждого значения int создаются новые объекты.

Обратитесь к программе ниже

В приведенном выше примере оба оператора печати печатают false, в отличие от предыдущего примера.

Чтобы избежать этой проблемы, мы всегда должны сравнивать целочисленные объекты, используя метод равенства вместо оператора ==. (метод equals в классе Integer перегружен и сравнивает два объекта по значению.)

Зачем java выполняет эту оптимизацию?

Это сделано для экономии памяти и оптимизации кода одновременно. Кэширование этих объектов позволяет лучше оптимизировать программы за счет повышения эффективности кэширования, поскольку не требуется создавать целочисленный объект для каждого литерала int, и его можно возвращать непосредственно из кэша. (объект Integer занимает около 12 байтов)

Теперь, почему перехватываются только целые числа в диапазоне от -128 до 127?

Этот диапазон кэша по умолчанию может зависеть от реализации JVM и может различаться.

Это также основано на предположении, что эти маленькие целые числа будут встречаться чаще, чем другие целые числа, поэтому имеет смысл избегать накладных расходов на повторное создание объекта Integer для одних и тех же значений ints.

Кэширование целых чисел в Java

При инициализации JVM создается целочисленный кеш для значений int в диапазоне от -128 до 127. Размер кеша можно контролировать с помощью флага.

-XX:AutoBoxCacheMax=‹размер›

Кэширование применяется только тогда, когда мы получаем объект Integer с помощью метода Integer.parseInt(i) или методов Integer.valueOf(i), неприменимо, когда мы создаем новый объект с помощью оператора new (new Integer( ));

ниже приведен фрагмент реализации класса Open-JDK Integer, показывающий этот кеш.

Перейдите по этой ссылке, чтобы увидеть реализацию класса Integer.

Реализация открытого JDK целочисленного класса